The easy way to deploy a Spring Boot application to production on Azure
Tags: spring, azure, java
Published: 2019-11-28 10:58:16

---
title: The easy way to deploy a Spring Boot application to production on Azure
published: true
description: This post shows how to deploy the Spring Petclinic sample application to Azure App Service, using GitHub Actions.
tags: spring, azure, java
---

In this blog post, we are going to deploy a classical Spring Boot application to production on Azure, with a strong focus on ease-of-use, both from a developer and operations perspective.

## Why "the easy way"?

While it is fun to [use Kubernetes the hard way](https://github.com/kelseyhightower/kubernetes-the-hard-way), if your goal is to deploy and host a Spring Boot application in production, your customer probably doesn't have the time and money to let you work like this.

We are aiming here at deploying and maintaining a production application with as little work as possible:

- As a developer, our goal is just to `git push` to production and not worry about anything else.
- As an ops engineer, our goal is to do the easiest setup possible, and not have any maintenance or scalability work.

## The sample application

For this blog post we will use [a fork of the famous Spring Petclinic](https://github.com/jdubois/spring-petclinic). This is a well-known and well-documented sample Spring Boot application, and we will detail the choices that were made in order to deploy it easily.

There is nothing specific about this application, so if you use a Spring Boot application (or even better, a [JHipster application](https://www.jhipster.tech/)!), you should be able to follow the next steps and be in the cloud very quickly.

## Azure App Service overview

There are many ways to deploy a Spring Boot application to Azure. You can obviously use a virtual machine (VM): you'll need to set up everything manually, take care of the OS and JVM maintenance, handle HTTPS and scalability yourself... So while it looks easy at first sight, it's time consuming and the maintenance is going to be a big issue.

We are going to use [Azure App Service](https://azure.microsoft.com/en-us/services/app-service/?WT.mc_id=devto-blog-judubois), which is a Platform-as-a-Service solution. It supports different languages, as well as Docker images, so it can effectively host any kind of application. It is also [very cost-efficient](https://azure.microsoft.com/en-us/pricing/details/app-service/linux/?WT.mc_id=devto-blog-judubois).

As a managed service, there is much less maintenance overhead than with a VM, and scalability is already included, which makes it a great way to host monolithic Spring Boot applications. If you have more complex needs, we recommend using [Azure Spring Cloud](https://azure.microsoft.com/en-us/services/spring-cloud/?WT.mc_id=devto-blog-judubois), which shares many similar concepts, but which targets microservices architectures.

## Jar or Docker?

[Azure App Service](https://azure.microsoft.com/en-us/services/app-service/?WT.mc_id=devto-blog-judubois) supports both Jar deployments and Docker deployments, which are both well-documented and popular ways to deploy Spring Boot applications.

We recommend using Jar deployment here: both the OS and the JVM will be managed (and supported!) by Microsoft, which means you will have far less maintenance work to do. For example, if a security vulnerability is discovered in the JVM, it will be automatically patched without any manual intervention.

## Azure App Service setup

First, we'll create an Azure resource group in which we will work:

- Go to the [Azure portal](https://portal.azure.com/?WT.mc_id=devto-blog-judubois).
- In the search box, look for "Resource groups".
- Create a new resource group called `spring-petclinic`.

Then, create the Azure App Service instance:

- In the Azure portal search box, look for "App Services".
- Create a new Web App in the `spring-petclinic` resource group, using Java 11 on Linux, as in the screenshot below:

![Creating App Service](https://thepracticaldev.s3.amazonaws.com/i/agna82dysckkj9adib26.png)

## MySQL setup

Like many Spring Boot applications, the Spring Petclinic uses the MySQL database: if you are using another database, like PostgreSQL, your setup should be similar.

Azure App Service has a feature called "MySQL in-app", that you can use to lower your hosting costs, as MySQL will run inside your Azure App Service instance. While this can be used in development, it comes with several important limitations and is not a production-grade database, so we are not going to use it here.

- Go to the [Azure portal](https://portal.azure.com/?WT.mc_id=devto-blog-judubois).
- In the search box, look for "Azure Database for MySQL".
- Create a MySQL server (and be careful to select the correct pricing tier for your usage!).
- Note your database name, your username and password, as we will need them later.

In your MySQL database, go to "Connection security", and select "Allow access to Azure services". You should also click on the "Add client IP" button to automatically add your current IP to the firewall rules, so you can access it from your current machine.

![MySQL firewall rules](https://thepracticaldev.s3.amazonaws.com/i/2h63af96ndfgzta0o6lg.png)

## Environment variables

The Spring Petclinic is configured using properties files, which are located in the `src/main/resources` directory. One of them is called `application-mysql.properties`, which means it will be used when the `mysql` Spring Boot profile will be triggered.

In the Azure App Service we created above, select the `Settings > Configuration` menu on the left.

We need to configure two different settings here:

- Set Spring Boot to use the `mysql` profile, using the `SPRING_PROFILES_ACTIVE` environment key.
- Override the database configuration using environment variables for the `SPRING_DATASOURCE_URL`, `SPRING_DATASOURCE_USERNAME` and `SPRING_DATASOURCE_PASSWORD` keys.

This configuration should look like the screenshot below:

![Environment variables](https://thepracticaldev.s3.amazonaws.com/i/878u16kvrhigjh484a10.png)

As we are handling secrets here, another solution it to use [Azure Key Vault](https://azure.microsoft.com/en-us/services/key-vault/?WT.mc_id=devto-blog-judubois). With Spring Boot, this can be configured using the [Azure Key Vault Secrets Spring Boot Starter](https://github.com/microsoft/azure-spring-boot/blob/master/azure-spring-boot-starters/azure-keyvault-secrets-spring-boot-starter/README.md). This adds some complexity to the project, and isn't more secure than environment variables in our particular use-case (in the end, both become Spring Boot properties, and can be read from the code), so for just storing one secret this is outside of the scope of this "deploy the easy way" article.

## Deploying using the Azure Webapp Maven plugin

Now that our App Service is configured, all we need to do is deploy our application. In this first solution, we are going to use the Azure Webapp Maven plugin. This is what most developers would use, as it's easily integrated inside their IDEs.

Inside your `pom.xml` file, add the following Maven plugin:

```xml
      <plugin>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-webapp-maven-plugin</artifactId>
        <version>1.8.0</version>
          <configuration>
            <schemaVersion>V2</schemaVersion>
            <resourceGroup>spring-petclinic</resourceGroup>
            <appName>jdubois-petclinic</appName>
            <region>westeurope</region>
            <pricingTier>B1</pricingTier>
            <runtime>
              <os>linux</os>
              <javaVersion>java11</javaVersion>
              <webContainer>java11</webContainer>
            </runtime>
            <deployment>
              <resources>
                <resource>
                  <directory>${project.basedir}/target</directory>
                  <includes>
                    <include>*.jar</include>
                  </includes>
                </resource>
              </resources>
            </deployment>
          </configuration>
      </plugin>
```

Of course, you will need to configure the correct parameters for your `resourceGroup`, `appName`, `region` and `pricingTier`.

This solution is very easy to use for developers, but it has a few drawbacks:

- Its configuration is stored inside the project's `pom.xml`, including configuration that should change depending on environments.
- It requires a local build and a manual work for the developer.

## Automating deployment with a GitHub Action

A newer alternative to the Azure Webapp Maven plugin is to use a GitHub Action.

You will need to authorize your GitHub Action to publish applications on Azure, here is how to do this:

- In the Azure portal, select your App Service and in the overview panel, click on `Get publish profile`. You will download a `.PublishSettings` file.
- In your GitHub project, go to `Settings > Secrets` and create a new secret called `azureWebAppPublishProfile`. Paste the content of the previous  `.PublishSettings` file into that secret.

Then, add the following GitHub Action to your project. Create a file called `.github/workflows/build-and-deploy.yml` and paste the following content in it:

```yaml
name: Build and deploy to Azure App Service

on:
  push:
    branches:
      - master

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Set up JDK 11
        uses: actions/setup-java@v1
        with:
          java-version: 11
      - name: Cache Maven archetypes
        uses: actions/cache@v1
        with:
          path: ~/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
            ${{ runner.os }}-maven-
      - name: Build with Maven
        run: mvn clean package
      - uses: azure/webapps-deploy@v1
        with:
          app-name: spring-petclinic
          publish-profile: ${{ secrets.azureWebAppPublishProfile }} # See https://github.com/Azure/actions-workflow-samples/tree/master/AppService
          package: '${{ github.workspace }}/target/*.jar'
```

Here is a brief description of this GitHub Action:

- It publishes an updated Azure App Service application as soon as code is pushed to the `master` branch. You can do a similar GitHub Action for other branches: you could have this setup for each project developer, or for each environment.
- It checks the latest code and installs Java 11.
- It uses the `actions/cache` GitHub Action to cache Maven archetypes: this considerably improves build times, so it is highly recommended.
- It builds and tests the application using Maven.
- It deploys the final application using the `azure/webapps-deploy` GitHub Action. This deployment could also have been made using the `Azure Webapp Maven plugin` we detailed in the previous section, but this GitHub Action allows to better decouple the code (the `pom.xml` doesn't have any specific Azure configuration or library), and it's also faster to execute.

## Final thoughts

Our two goals are fulled reached:

- Developers only need to `git push` to deploy their Spring Boot application, without even needing to know anything about Azure App Services.
- Operations engineers had to do a minimal setup (creating the MySQL and App Service instances, and configuring 4 environment variables), but now the application can run in production without much maintenance. The OS and the JVM will be automatically patched and supported by Microsoft, and scalability is included.

In order to achieve those goals, we didn't have to modify any code in our Spring Boot application. Using GitHub Actions to deploy, all we needed to do is add a hidden file inside the `.github` repository.

If you want to have a closer look at the final application, [my fork of Spring Petclinic is available here](https://github.com/jdubois/spring-petclinic).