Spring and Angular applications on Azure (7 Part Series)
This blog post is part of a series on "deploying a Spring Boot and Angular application on Azure", here is the full list of posts:
- Creating a Spring Boot and Angular application for Azure (1/7)
- Creating and configuring Azure Web App and MySQL to host a Spring Boot application (2/7)
- Using Azure Pipelines to build, test and deploy a Spring Boot and Angular application (3/7)
- Using Azure Application Insights with Spring Boot (4/7)
- Using Azure Application Insights with Angular (5/7)
- Configuring Azure CDN to boost Angular performance (6/7)
- Configuring Azure Redis Cache to boost Spring Boot performance (7/7)
There are several ways to deploy a Spring Boot application to Azure. One of the easiest way is to use the Maven Plugin for Azure App Service. For our use-case, we want to go beyond the simple "Hello, world" application, and thus we are going to set up a full CI/CD (Continuous Integration/Continuous Deployment) solution using Azure Pipelines.
As always, we are budget-conscious here: Azure Pipelines provides a generous free tier which should be largely enough for us, so we shouldn't pay anything.
In order to build and test our application with Azure Pipelines, we will need an
azure-pipelines.yml file at the root of our project.
With JHipster, we're in luck, we just need to run
jhipster ci-cd and answer a couple of questions to have a very complete Azure Pipelines configuration.
You can check the generated file on this commit.
This pipeline will build and test the application (both the Spring Boot back-end and the Angular front-end), so it is a "Continuous Integration" pipeline. If you need more informations on Azure Pipelines tasks, you should refer to the Azure Pipelines Documentation. Creating a simple Maven build is very easy, then doing more complex configurations like we do with JHipster might require a bit more time.
In the previous section, we created an
azure-pipelines.yml file: we are going to add a new task to it, in order to publish a production build, once all the tests have passed. As a result, it will not do only "Continuous Integration" anymore, but full "Continuous Deployment".
azure-pipelines.yml file, and add at the end of it:
- script: ./mvnw package -Pprod -DskipTests displayName: 'BUILD: creating production build' - task: CopyFiles@2 inputs: SourceFolder: 'target' Contents: '*.jar' TargetFolder: '$(Build.ArtifactStagingDirectory)' - task: PublishBuildArtifacts@1 inputs: pathtoPublish: '$(Build.ArtifactStagingDirectory)' artifactName: bugtracker
We are using 3 tasks in fact:
- One for doing a production build with JHipster. Please note that here we are skipping the tests are they are supposed to have passed before.
- Another one to copy the generated file JAR file to a directory where artifacts are being stored.
- And a last one to take that artifact and publish it.
This will automatically publish an artefact of your production build in Azure Pipelines.
WARNING As Azure Web App uses an artefact which should be named
app.jar, we're going to have to name our artefact correctly. The easiest way to do it, is to create it directly with the correct name, using the
finalName attribute in your
<build> <finalName>app</finalName> ... </build>
You can check the changes we just made to set up "Continuous Deployment" on this commit.
If you haven't done it yet, push your application to GitHub: if you don't want your application to be public, remember that GitHub provides free unlimited private repositories.
Once your application is on GitHub, go to the GitHub marketplace to install and setup Azure Pipelines.
You can then log in to Azure Devops to set up your Azure Pipelines:
- Create a new project.
- On the left-hand menu, select "Pipelines > Builds" and create a "new pipeline".
- Select "GitHub", and choose the GitHub project you have just created in the steps above.
- As we have created an
azure-pipelines.ymlfile in the previous section, it will be automatically picked up, so you just need to "Run" it (using the button on the top right) to watch your application being built by Azure Pipelines.
As this build is a "full stack" build, it will compile, package and test all your Spring Boot and Angular code. As you can imagine, this is a rather complex, and this should take a bit more than 5 minutes to complete.
Once Azure Pipelines has built your application a first time, it will have published an artefact of the project. A new "Release" button will appear on the top right corner: click on it to create a new release.
You will see there your published artefact, and will be able to add new "stages" to it, in order to deploy it to production automatically.
Create a new "stage" and choose "Deploy a Java App to Azure App Service". Once this stage is created, open it and:
- Give it a meaningful name
- Connect it to your Azure subscription: you will need to click on the "Authorize" button and follow an authorization wizard
- Change the application type to "Web App on Linux" as this is what we created in the previous blog post
- Select your application service name
Then, you need to modify the 2 tasks configured with this stage:
- Delete the first task, called "Deploy WAR to Azure App Service", as we are not deploying a WAR.
- Enable the second task, called "Deploy JAR to Azure App Service".
You can now go to the "Pipelines > Releases" and click on the "Create release" button. This should take the previously generated artefact (made by the
azure-pipelines.yml), and deploy it automatically to your Azure Web App instance.
You can now connect to your application, and use it in production. As this is a JHipster application, here are a few tips to remember:
- There are 2 accounts by default,
- The database schema is managed using Liquibase, so when the application starts it automatically update the database schema. That schema was created in the previous blog post, using MySQL Workbench.
- If you ran the application in developement on your local computer, JHipster filled up your database with some dummy data using faker.js. In production mode, as you are supposed to use some real data, your database will not have this data by default.
Now, each time our build passes, our application will be automatically deployed to production, where it will be automatically managed by Azure Web Apps. No more production issues, just "git push" and you're done!
You might have noticed that the application is a bit slow to start-up, it takes a bit more than 1 minute. Our worst-case scenario was 100 seconds, so it should be up under 2 minutes, but still that's a lot of time!
We have two culprits here: JHipster and the hardware. We can indeed make JHipster start in about one-third of that time, through various tunings (mostly disabling features like Liquibase). The performance gain can be important as here we are at the limit of the JVM memory, so the garbage collector is working hard, and removing a few features will help it a lot.
Then, the hardware selected isn't very good, as we wanted to be budget-conscious, and selected a "B1" box: it is free for the first month, and then very inexpensive (about $30 per month). This is why our memory is too limited, and also why our CPU is limited. Azure counts CPU power in "ACU", which means Azure Compute Units, and a B1 box as only 100 ACUs.
Testing a more powerful instance is surprisingly easy: in your Azure Web App, select "Scale up", and choose a "P2V2" instance. The upgrade is done on the fly! On this new hardware, which has 420 ACUs (so more than 4 times the compute power of a "B1"), start-up time is now only 15 seconds. Of course, you can scale down at any time and come back to the "B1" instance.