Deploy a Java application with Open Liberty or WebSphere Liberty on Azure Container Apps

This article shows you how to run Open Liberty or WebSphere Liberty on Azure Container Apps. You do the following activities in this article:

  • Run your Java, Java EE, Jakarta EE, or MicroProfile application on the Open Liberty or WebSphere Liberty runtime.
  • Build the application Docker image using Liberty container images.
  • Deploy the containerized application to Azure Container Apps.

For more information on Open Liberty, see the Open Liberty project page. For more information on IBM WebSphere Liberty, see the WebSphere Liberty product page.

This article is intended to help you quickly get to deployment. Before going to production, you should explore Tuning Liberty.

If you're interested in providing feedback or working closely on your migration scenarios with the engineering team developing WebSphere on Azure solutions, fill out this short survey on WebSphere migration and include your contact information. The team of program managers, architects, and engineers will promptly get in touch with you to initiate close collaboration.

Prerequisites

  • An Azure subscription. If you don't have an Azure subscription, create a free account before you begin.
  • Prepare a local machine with either Windows or Unix-like operating system installed - for example, Ubuntu, macOS, or Windows Subsystem for Linux.
  • Install the Azure CLI 2.53.0 or above to run Azure CLI commands.
  • Install a Java SE implementation version 17 or later - for example, Microsoft build of OpenJDK.
  • Install Maven 3.5.0 or higher.
  • Install Docker for your OS.
  • Ensure that Git is installed.

Sign in to Azure

If you haven't done so already, sign in to your Azure subscription by using the az login command and follow the on-screen directions.

az login

Note

You can run most Azure CLI commands in PowerShell the same as in Bash. The difference exists only when using variables. In the following sections, the difference is addressed in different tabs when needed.

If you have multiple Azure tenants associated with your Azure credentials, you must specify which tenant you want to sign in to. You can do this with the --tenant option - for example, az login --tenant contoso.onmicrosoft.com.

If you have multiple subscriptions within a single tenant, make sure you are signed in with the one you intend to use by using az account set --subscription <subscription-id>.

Create a resource group

An Azure resource group is a logical group in which Azure resources are deployed and managed.

Create a resource group called java-liberty-project using the az group create command in the eastus location. This resource group is used later for creating the Azure Container Registry (ACR) instance and the Azure Container Apps instance.

export RESOURCE_GROUP_NAME=java-liberty-project
az group create --name $RESOURCE_GROUP_NAME --location eastus

Create an ACR instance

Use the az acr create command to create the ACR instance. The following example creates an ACR instance named youruniqueacrname. Make sure youruniqueacrname is unique within Azure.

export REGISTRY_NAME=youruniqueacrname
az acr create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $REGISTRY_NAME \
    --sku Basic \
    --admin-enabled

After a short time, you should see a JSON output that contains the following lines:

  "provisioningState": "Succeeded",
  "publicNetworkAccess": "Enabled",
  "resourceGroup": "java-liberty-project",

Connect to the ACR instance

You need to sign in to the ACR instance before you can push an image to it. If you choose to run commands locally, ensure the docker daemon is running, and run the following commands to verify the connection:

export ACR_LOGIN_SERVER=$(az acr show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $REGISTRY_NAME \
    --query 'loginServer' \
    --output tsv)
export ACR_USER_NAME=$(az acr credential show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $REGISTRY_NAME \
    --query 'username' \
    --output tsv)
export ACR_PASSWORD=$(az acr credential show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $REGISTRY_NAME \
    --query 'passwords[0].value' \
    --output tsv)

docker login $ACR_LOGIN_SERVER -u $ACR_USER_NAME -p $ACR_PASSWORD

You should see Login Succeeded at the end of command output if you've logged into the ACR instance successfully.

Create an environment

An environment in Azure Container Apps creates a secure boundary around a group of container apps. Container Apps deployed to the same environment are deployed in the same virtual network and write logs to the same Log Analytics workspace. Use the az containerapp env create command to create an environment. The following example creates an environment named youracaenvname:

export ACA_ENV=youracaenvname
az containerapp env create \
    --resource-group $RESOURCE_GROUP_NAME \
    --location eastus \
    --name $ACA_ENV

If you're asked to install an extension, answer Y.

After a short time, you should see a JSON output that contains the following lines:

  "provisioningState": "Succeeded",
  "type": "Microsoft.App/managedEnvironments"
  "resourceGroup": "java-liberty-project",

Create an Azure SQL Database

In this section, you create an Azure SQL Database single database for use with your app.

Create a single database in Azure SQL Database by following the Azure CLI steps in Quickstart: Create a single database - Azure SQL Database. Execute the steps up to, but not including Query the database. Use the following steps as you go through the article, then return to this document after you create and configure the database server:

When you reach the Set parameter values section of the quickstart, output and save aside the values of variables in the code example labeled Variable block, including resourceGroup,server, database, login, and password. Define the following environment variables after replacing placeholders <resourceGroup>,<server>, <database>, <login>, and <password> with these values.

export DB_RESOURCE_GROUP=<resourceGroup>
export DB_SERVER_NAME=<server>.database.windows.net
export DB_NAME=<database>
export DB_USER=<login>
export DB_PASSWORD=<password>

If you want to test the application locally later, use the following steps to ensure your client IPv4 address is allowed to connect:

  1. In the portal, search for and select SQL databases, and then select your database from the list.

  2. Select Overview.

  3. Ensure the Getting started tab is selected in the middle of the page.

  4. Under Configure access, select Configure.

  5. Select Add your client IPv4 address.

  6. Select Save.

  7. You can find and configure Firewall rules in the Networking pane and Public access tab.

    Screenshot of firewall rules - allow client access.

Configure and build the application image

To deploy and run your Liberty application on Azure Container Apps, containerize your application as a Docker image using Open Liberty container images or WebSphere Liberty container images.

Follow the steps in this section to deploy the sample application on the Liberty runtime. These steps use Maven.

Check out the application

Use the following commands to prepare the sample code for this guide. The sample is on GitHub.

git clone https://github.com/Azure-Samples/open-liberty-on-aca.git
cd open-liberty-on-aca
git checkout 20231026

If you see a message about being in detached HEAD state, this message is safe to ignore. It just means you have checked out a tag.

This article uses java-app. Here's the file structure of the application:

java-app
├─ src/main/
│  ├─ liberty/config/
│  │  ├─ server.xml
│  ├─ java/
│  ├─ resources/
│  ├─ webapp/
├─ Dockerfile
├─ Dockerfile-wlp
├─ pom.xml

The directories java, resources, and webapp contain the source code of the sample application. The code declares and uses a data source named jdbc/JavaEECafeDB.

In the java-app root directory, there are two files to create the application image with either Open Liberty or WebSphere Liberty.

In directory liberty/config, the server.xml file is used to configure the DB connection for the Open Liberty and WebSphere Liberty cluster.

Build the project

Use the following command to build the application:

cd <path-to-your-repo>/java-app
mvn clean install

If the build is successful, you should see output similar to the following at the end of your build.

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  22.651 s
[INFO] Finished at: 2023-10-26T18:58:40-04:00
[INFO] ------------------------------------------------------------------------

If you don't see this output, troubleshoot and resolve the problem before continuing.

(Optional) Test your project locally

You can now use the following steps to run and test the project locally before deploying to Azure. For convenience, use the liberty-maven-plugin. To learn more about the liberty-maven-plugin, see Building a web application with Maven. For your application, you can do something similar using any other mechanism, such as your local IDE.

Note

If you selected a "serverless" database deployment, verify that your SQL database has not entered pause mode. One way to do this is to log in to the database query editor as described in Quickstart: Use the Azure portal query editor (preview) to query Azure SQL Database.

  1. Start the application using liberty:run. liberty:run uses the database related environment variables defined in the previous step.

    cd <path-to-your-repo>/java-app
    mvn liberty:run
    
  2. Verify the application works as expected. You should see a message similar to [INFO] [AUDIT] CWWKZ0003I: The application javaee-cafe updated in 1.930 seconds. in the command output if successful. Go to http://localhost:9080/ in your browser to verify the application is accessible and all functions are working.

  3. Press Ctrl+C to stop.

Build the image

You can now run the docker buildx build command to build the image, as shown in the following example:

cd <path-to-your-repo>/java-app

# If you are running with Open Liberty
docker buildx build --platform linux/amd64 -t javaee-cafe:v1 --pull --file=Dockerfile .

# If you are running with WebSphere Liberty
docker buildx build --platform linux/amd64 -t javaee-cafe:v1 --pull --file=Dockerfile-wlp .

(Optional) Test the Docker image locally

You can now use the following steps to test the Docker image locally before deploying to Azure:

  1. Run the image using the following command. This command uses the database related environment variables defined previously.

    docker run -it --rm -p 9080:9080 \
        -e DB_SERVER_NAME=${DB_SERVER_NAME} \
        -e DB_NAME=${DB_NAME} \
        -e DB_USER=${DB_USER} \
        -e DB_PASSWORD=${DB_PASSWORD} \
        javaee-cafe:v1
    
  2. After the container starts, go to http://localhost:9080/ in your browser to access the application.

  3. Press Ctrl+C to stop.

Upload image to ACR

Next, upload the built image to the ACR you created in the previous steps.

If you haven't already done so, use the following command to sign in to the ACR:

docker login -u ${ACR_USER_NAME} -p ${ACR_PASSWORD} ${ACR_LOGIN_SERVER}

Use the following commands to tag and push the container image:

docker tag javaee-cafe:v1 ${ACR_LOGIN_SERVER}/javaee-cafe:v1
docker push ${ACR_LOGIN_SERVER}/javaee-cafe:v1

Deploy the application to Azure Container Apps

Use the following commands to create an Azure Container Apps instance to run the app after pulling the image from the ACR. This example creates an Azure Container Apps instance named youracainstancename.

export ACA_NAME=youracainstancename
az containerapp create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $ACA_NAME \
    --image ${ACR_LOGIN_SERVER}/javaee-cafe:v1 \
    --environment $ACA_ENV \
    --registry-server $ACR_LOGIN_SERVER \
    --registry-username $ACR_USER_NAME \
    --registry-password $ACR_PASSWORD \
    --target-port 9080 \
    --env-vars \
        DB_SERVER_NAME=${DB_SERVER_NAME} \
        DB_NAME=${DB_NAME} \
        DB_USER=${DB_USER} \
        DB_PASSWORD=${DB_PASSWORD} \
    --ingress 'external'

Successful output is a JSON object including the property "type": "Microsoft.App/containerApps".

Test the application

Use the following command to get a fully qualified url to access the application:

echo https://$(az containerapp show \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $ACA_NAME \
    --query properties.configuration.ingress.fqdn \
    --output tsv)

Open a web browser to the URL to access and test the application. The following screenshot shows the running application:

Screenshot that shows the Java liberty application successfully deployed on Azure Container Apps.

Clean up resources

To avoid Azure charges, you should clean up unnecessary resources. When the cluster is no longer needed, use the az group delete command to remove the resource group, container registry, container apps, database server, and all related resources.

az group delete --name $RESOURCE_GROUP_NAME --yes --no-wait
az group delete --name $DB_RESOURCE_GROUP --yes --no-wait

Then, use the following command to remove the container image from your local Docker server:

docker rmi -f ${ACR_LOGIN_SERVER}/javaee-cafe:v1

Next steps

You can learn more from the references used in this guide:

To explore options to run WebSphere products on Azure, see What are solutions to run the WebSphere family of products on Azure?