Wednesday, 29 May 2024

Deploy a Dockerized Spring Boot app to Azure App Service

Deploy a Dockerized Spring Boot app to Azure App Service

 

Cloning the demo project

Clone the sample project by running the following command. The sample project is an exchange rate API with three endpoints namely:

S/NEndpointMethodFunction
1./currencyGETGet all currencies supported by the API
2./ratesGETGet all the exchange rates for all the supported currencies
3./rates/{currency}GETGet the exchange rates for a single currency
git clone https://github.com/CIRCLECI-GWP/spring-docker-api

Next, go to the root of the new folder created by the previous command (i.e spring-docker-api). Set up and run the project by running the following commands.

cd spring-docker-api

mvn -B -DskipTests clean package

mvn spring-boot:run

The mvn -B -DskipTests clean package command will clear the target directory if existed, builds the project and skip test during the build. Finally, the mvn spring-boot:run command will run the project on the default port.

By default, your application will be served to port 8080. Navigate to http://127.0.0.1:8080/rates in order to review the JSON response.

Running application locally

Dockerizing the project

In the root of the project, create a new file named Dockerfile. Note that this file has no extension. Add the following to the newly created Dockerfile.

FROM openjdk:18

WORKDIR /app
COPY . /app

RUN ./mvnw  -B -DskipTests clean package

EXPOSE 8080

CMD ["java", "-jar", "target/exchangeRates-0.0.1-SNAPSHOT.jar"]

The FROM key specifies the base image for the container (OpenJDK). Next, the working directory is set using the WORKDIR key. All the files in the project will be copied to the app and then using the maven wrapper script a new JAR file will be built. Next, port 8080 is exposed for external connections and the command to run the application is specified using the CMD key.

To build the container, run the following command.

docker build -t exchange-rate-api .

If you are on a MacBook Pro with an Apple M1 Pro chip, kindly use the following command to build your image.

docker build --platform=linux/amd64 -t exchange-rate-api .

This command used the --platform argument to specify the target architecture that will run the image on Azure. This is a known issue and you can read more about it here.

Once the build process is completed, you can restart the application using the following command - if you did not stop the application previously, you can do so now to avoid port conflicts.

docker run -it -p 8080:8080 exchange-rate-api

This command maps port 8080 on the container to port 8080 on your workstation and runs the image. Go to http://127.0.0.1:8080/rates again for the JSON response.

Deploying to Azure

Deploying the application to Azure involves two steps. First, you will build a docker image of your application and push it to the Azure Container Registry. Once that is completed you will create a new Web App which is based on the Docker image you created.

Creating an Azure Container Registry

If you do not have one already, create an account on Azure. Navigate to the Azure portal dashboard and click Create a resource.

Create Azure Service

Then select Containers > Container Registry to create a new registry.

Create azure registry

On the registry creation page, input the required details for the registry, similar to what we have below.

Create container registry

Click Review + Create and you will be redirected to a page where you can review the registry information. Once you are good with it, click Create to set up a new registry instance.

Obtaining Access Key from the Registry

In this section, you will enable Docker access in the Azure container registry. This is crucial to the deployment process as it enables you to remotely log in to the Azure container registry through the CLI and be able to push images to it.

To do that, once the registry resources have been created successfully, open it and locate the Access Keys link under the Settings section.

Obtaining Access Key

This will show you the registry name and login server. Enable the Admin user using the toggle button. Once enabled, copy the username and any of the passwords, preferably the first one. Keep this safe as it will be used later in the tutorial.

Pushing the Docker image to Azure Registry

The next step is to tag the image you created in the previous step, before pushing it to the registry. For the tag, use the login server and registry name as shown in the command below.

docker tag exchange-rate-api springbootapi.azurecr.io/springbootapi:latest

The next step is to log in to the Azure container registry created earlier and push the container image to it. Issue the following command from the terminal for that purpose:

docker login -u DOCKER_USER -p DOCKER_PASS springbootapi.azurecr.io

Replace the following placeholders with appropriate values:

  • DOCKER_USER: The username obtained for the container registry
  • DOCKER_PASS: The password from the container registry.

Once you are logged in, use the following command to push the image to the Azure registry.

docker push springbootapi.azurecr.io/springbootapi:latest

This will deploy the image to the Azure registry:

View Azure Registry

Creating an Azure Web App for the container

Next, you will create an Azure Web App and connect it with the container image. Navigate to the Azure portal homepage and click Create a resource.

Then select Containers > Web App for Containers to create a new web app service instance.

Create Container Web App

You will be redirected to the Create Web App page. Select an Azure subscription and a resource group, create a new resource group if you have not done that, and name your Web App as preferred. I have named mine spring-docker-api-demo. Docker container should be selected by default, otherwise, select it.

Create Web app

Next, click on the Docker tab and select the image source and its respective docker image.

Docker Tab

Click Review + Create and you will be redirected to a page where you can review the web app details. Once you are good with it, click Create to set up a new Azure web app.

Once the process is completed, you can visit the URL generated for your application, you will be able to view the app as deployed to Azure. The URL is in this format https://<APP_NAME>.azurewebsites.net. Ensure that you replace the APP_NAME placeholder as defined above. You will see a page similar to the following:

App deployed

Enabling continuous deployment

To ensure that the app will receive the update each time your Docker image is updated, you need to enable continuous deployment for the web app service. To do that, click on the web app name and then click on Deployment Center under the Deployment section and scroll down. Under the settings tab and turn on continuous deployment by checking the radio button. Click Save to persist the changes.

Enable continuous deployment

With continuous deployment selected, the web app will trigger a new deployment of the application each time the Docker image is rebuilt on Azure Container Registry.

Next, you need to add the pipeline configuration for CircleCI to automate testing and run the appropriate commands to build and push the container image to Azure.

At the root of your project, open the config.yml file within the .circleci folder and update its content with the following:

version: 2.1
orbs:
  docker: circleci/docker@2.1.4
jobs:
  build-and-test:
    docker:
      - image: cimg/openjdk:19.0.1
    steps:
      - checkout
      - run:
          name: Build
          command: mvn -B -DskipTests clean package
      - run:
          name: Test
          command: mvn test

  deploy-docker-image:
    executor:
      name: docker/docker
      tag: "3.6"
    steps:
      - checkout
      - docker/install-docker-tools
      - setup_remote_docker:
          version: 20.10.14
          docker_layer_caching: true

      - run:
          name: "Build and push Docker image"
          command: |
            docker login -u $DOCKER_USER -p $DOCKER_PASS springbootapi.azurecr.io
            docker build -t springbootapi.azurecr.io/springbootapi:latest .
            docker push springbootapi.azurecr.io/springbootapi:latest

workflows:
  test-and-deploy:
    jobs:
      - build-and-test
      - deploy-docker-image:
          requires:
            - build-and-test

Let’s look through the configuration and understand what is going on.

The CircleCI configuration always starts with the version. For this article, we use version 2.1.

The next part of the configuration specifies two different jobs:

  • build-and-test
  • deploy-docker-image

The build-and-test job uses the CircleCI Open JDK docker image as the base image, checks out our project from GitHub, installs the project’s dependencies, builds the application, and runs the tests.

The deploy-docker-image job creates a Docker image for the code pulled from the GitHub repository and updates the Azure Container Registry with the latest version of the container. The requires key specifies that the deploy-docker-image should not run until the build-and-test job is complete.

Connecting the application to CircleCI

The next step is to set up a repository on GitHub and link the project to CircleCI. Review Pushing a project to GitHub for instructions.

Log in to your CircleCI account. If you signed up with your GitHub account, all your repositories will be available on your project’s dashboard.

Click Set Up Project next to your spring-docker-api project.

Select project

You will be prompted to enter the name of the branch where your code is housed on GitHub. Click Set Up Project once you are done.

Setup project

Your first workflow will start running.

The deploy-docker-image job will fail because we are yet to provide our Azure Container Registry credentials.

To fix that, you will need to add username and password environment variables. Click Project Settings.

Click the Environment Variables button on the left sidebar and create these variables:

  • The DOCKER_USER variable is the username obtained for the container registry
  • The DOCKER_PASS variable is the password from the container registry

Env Variables

Go back to the dashboard. Click Rerun Workflow from Start.

Your workflow will run successfully.

Workflow runs successfully

To make sure that everything works properly, let’s make an update to the application. For this, we’ll add a new supported currency to the application.

Update the expectedCurrencies array in src/test/java/com/example/exchangeRates/ExchangeRatesApplicationTests.java to match the following.

final String[] expectedCurrencies = {"EUR", "GBP", "NGN", "USD", "YEN", "CFA"};

In the same vein, update the supportedCurrencies array in src/main/java/com/example/exchangeRates/service/ExchangeRatesService.java.

final String[] supportedCurrencies = {"EUR", "GBP", "NGN", "USD", "YEN", "CFA"};

Next, commit and push the changes to your GitHub repository.

git commit -am "Add support for CFA"

git push origin main

Head back to your CircleCI dashboard and you will see that a new build has been completed.

New build completed

You can also open the appropriate URL in your browser to see the rates for the new currency.

Release updates

Serverless platform with Azure Container Apps

 

Serverless platform with Azure Container Apps

Azure Container Apps

For sure, most of IT administrators love containers but don’t have time enough to manage their own Kubernetes platform. It is time consuming and for beginner it is not easy to manage. Maybe you just want to test your application on Kubernetes in order to migrate on this platform in the future, or you just don’t have the skills to manage complex container orchestrators.

Well, probably Azure Containers Apps is for you. Azure Container Apps is serverless, so just focus on your code and that’s all! Of course, Azure Containers Apps (ACA) is based on Kubernetes platform.

I know the first question is « why do I need another K8S services in Azure? ». Microsoft provides more details on the differences here: https://docs.microsoft.com/en-us/azure/container-apps/compare-options

  • AKS (Kubernetes service) is a fully managed Kubernetes service in Azure
  • ACI (Container Instances) allows you to run containers on a single pod of Hyper-V isolated containers on-demand.
  • Web Apps for containers (Azure App Service) is fully managed. Web applications may be deployed using code or containers

Below are some example scenarios for ACA (from the Microsoft Documentation)

Example scenarios for ACA

Getting started

In this guide, we will create our first Azure Container Apps using the Azure portal.

Open the Azure portal and go to « Container Apps », then click « Create »

Container Apps

You must create the first environment byu entering the name of the environment and selecting the region.

What is an environment?

An environment is a secure boundary, you can deploy many containers apps in the same environment, so they will use the same virtual network and you will be able to write logs to the same Log Analytics workspace.

Create container apps environment

Click next and select:

  • Your subscription
  • Your resource group
  • The container app name
  • And the container apps environment (previously created or create a new one)

Create container app

Click next deep dive into the app settings tab. You must create a container, in my case I will use a WordPress image located on docker hub registry.

What is a container?

It is similar to Kubernetes Pods. Each container app can contain multiple containers, and they all share the same life cycle, the same disk and can communicate directly with each other. More information here: https://docs.microsoft.com/en-gb/azure/container-apps/containers

If you just want to test ACA, with a default image, you can use the quickstart image (see screenshot below)

App settings

Else, if you want to test with your own image, uncheck the quickstart checkbox in order to enter more information

Quickstart checkbox

Then, you must configure the ingress settings. Azure Container Apps allows you to expose your container app to the public web by enabling ingress. So you don’t need a Public IP Address or a Load Balancer. Just expose the target port and click next.

Application ingress settings

Click « review + create » to deploy your ACA.

If you want to deploy ACA with the default quickstart image, you can add another container image by clicking « Add » in the container image section.

Add another container image

Enter all the required information:

Enter all the required information

Click add to confirm and then you should see two images

Container image

The quickstart image is very basic, it is just a single web HTML page:

Single web HTML page

In my case I deployed WP using a container image located on Docker Hub registry

WordPress

Set up your database connection

Deploying Docker Images To Azure Container Apps

Deploying Docker Images To Azure Container Apps 



1. Once you’re in the configuration settings, you must fill in the following details that have a red asterisk.

Azure Container Apps using Docker images

2. The Container Apps Environment field will be created automatically by default, but you can also configure it based on your needs. When you click Create new, you’ll be taken to the Create Container Apps Environment page, which includes the following tabs:

    • Basics – configure environment name and zone redundancy.
    • Monitoring – create a log analytics workspace to store application logs.
    • Networking – select the default or custom virtual network.

Deploying Docker Images to Azure Container Apps

3. Next is the app settings tab; we need to untick the “Use quickstart image” to use a custom image from Docker Hub. After that, we need to select an image from Docker and the container image that we will use is Grafana.

Deploying Docker Images to Azure Container Apps

4. After you copied the Grafana image and tag, fill in the following details: 

Deploying Docker Images to Azure Container Apps

Note: If you don’t specify the image’s tag version, you’ll always get the latest version.

5. If you scroll down, you’ll see an Application ingress settings section. Don’t forget to enable the ingress, select “Accepting traffic from anywhere”, and the target port of the container. This is the port your container is listening on that will receive traffic.

Deploying Docker Images to Azure Container Apps

The main reason why we need to enable ingress is so we can generate an application URL. Also, the insecure connections option will just generate an HTTP URL.

6. For the tags tab, this is optional, but for best practices, Azure recommends that you should add always add tags to organize your Azure resources.

Deploying Docker Images to Azure Container Apps

7. Before creating the container app, review all the details, and once you’re done, click Create, then, you’ll be redirected to the Deployment is in progress page. The deployment will take a few minutes to be completed.

Deploying Docker Images to Azure Container Apps

8. To verify the app that you’ve just deployed, go to resource and find the application URL.

Deploying Docker Images to Azure Container Apps

9. After clicking the application URL, you’ll be redirected to the Grafana app container.

Deploying Docker Images to Azure Container Apps

10. That’s it! Now you’ve deployed a Grafana image from Docker Hub with a few steps. Grafana is basically a dashboard to monitor the health and performance of all your resources in one platform. If you want to know about its features and how it works, then check out this article.