Making Java Spring Boot (with containerization) work with Azure DevOps
Recently, many peoples ask me about how to make Java Spring Boot application with containerization and corresponding DevOps implementation. I created number of samples Java Spring Boot web applications (with containerization) in GitHub to make everyone easier to kick start on this topic. In this article, I would like to share how to make end-to-end DevOps works with Azure solution stack which including Azure DevOps, Azure Kubernetes Service (AKS), Azure Container Registry (ACR) and Azure Web Application Firewall (WAF).
For basic usage understanding of Azure DevOps, you can refer to my previously article about “Making MEAN stack work with Azure DevOps”.
In this article, I will use my sample “Java Web App in Spring Boot framework with Containerization” in Github for deployment. It’s also contain how to build/containerize locally with maven and Docker CE.
Wait… let me tell you the high-level flows and architecture before going to details…
Left to Right…
- Developer local development environment (Mac/Windows) which installed JDK, Maven, Docker CE. And it’s also installed free code editor Visual Studio Code as it have lots of open-sources friendly extension debugger.
- Git Stage, Commit and Push (by command or GUI via VS Code) from local to Azure DevOps Repos.
- Build Pipeline is being triggered as there are new commit from Repos. Then Build Pipeline perform Maven build, Docker build and push the build container image to ACR.
- Release Pipeline is being triggered as there are new Build from Build Pipeline. Then Release Pipeline ask AKS to perform POD container image update (with latest build number) which pull from ACR.
- Second part of Release Pipeline is being triggered after container image updated. Then Release Pipeline will ask Test Plans to perform web application load testing.
Right to Left…
- Access web app from mobile device.
- WAF validate web app access request is valid or not (malicious attacks).
- WAF pass through valid web app access request to back-end listener which is inside Internal Virtual Network and hosted by Service expose from AKS.
For Azure Admin…?
Little bit long sharing, we have 2 stages to make it works…
All right, let’s get started…
Stage 1: Setup Build Pipeline which triggered from Repos
- Actually, there are “Set up build” button in your Repos page, just click on it.
2. In New pipeline page, click “Use the classic editor”.
3. There are lots of template build task packages. This time, I will use “Maven” template, click on Apply.
4. There are 3 jobs will automatically add for this Pipeline. First, make a meaningful name of your Build Pipeline, I use “sb-web-sample-01-docker-ado-Maven-CI” this time. Then select “Agent pool”, I use “Hosed Ubuntu 1604” this time which is Ubuntu Linux OS based build server. And you can define your Maven POM file location. Then you can leave 3 auto-created agent job configuration by default, it will help you to perform Maven build based on your POM file definition and publish it to artifact drop folder.
5. After Maven build job done, we need to build container image based on your dockerfile definition and then push to your private container registry (ACR). It’s little tricky part in here, as my ACR enabled Virtual Network Service Endpoint which mean only resources in Virtual Network/Subnet or trusted IP address/range to access/push/pull container images. In this case, as we are using Microsoft Hosted agent which is not sitting inside your Virtual Network/Subnet. So, that’s mean you’re required to deploy Azure DevOps’ Self-Hosted Agents which deploy inside your Virtual Network/Subnet in Azure Virtual Machine. This time, I’m trying to make something interesting/tricky, I use Bash shell command to check Microsoft Hosted agent (Ubuntu 1604)’ IP address, suppose this build agent IP is dynamic as it’s host/manage by Microsoft. After I obtained the build agent IP, I use Azure CLI command line to update ACR’ configuration and make this build agent IP as trusted IP.
Interesting? Let’s add 1 more Agent job by press + button. Then enter “bash” and select “Bash” task.
6. In Bash task configuration, select type to “Inline” and input script content as below.
ip=$(curl -s http://ipinfo.io/json | jq ‘.ip’)
echo “##vso[task.setvariable variable=ado_host_ip;]$ip”
7. Then, this step is optional, let’s add 1 more “Bash” task to double check I’m able to retrieve defined variable in previous task. In Bash task configuration, select type to “Inline” and input script content as below.
8. Now we will add new task to use Azure CLI to update ACR configuration. Let’s add 1 more Agent job by press + button. Then enter “azure cli” and select “Azure CLI” task.
9. In Azure CLI task configuration, select your Azure Subscription, select “Inline script” in Script Location and input script content as below.
az acr network-rule add -n YOUR_ACR_NAME --ip-address $(ado_host_ip)
10. Now we’re ready to start Docker build and push to ACR. Let’s add 1 more Agent job by press + button. Then enter “docker” and select “Docker” task.
11. In Docker task configuration, select your ACR in Container Registry, select build in Command, select your Dockerfile location, enter $(Build.BuildId) in Tags. In this sharing, I will base on latest Build ID to ask AKS to update POD container by latest Build ID tag.
12. Let’s add 1 more “Docker” task to push your build container image to ACR. In this Docker task configuration, select your ACR in Container Registry again, select push in Command, enter enter $(Build.BuildId) in Tags.
OK, all configuration for Build Pipeline has been done. Now you can click “Save & queue” button to initiate first build.
Then, wait for a while, you should see your initial build is completed, click on that build.
Stage 2: Setup Release Pipeline which triggered from Build Pipeline
- In your initial successful build, click “Release” button.
2. There are lots of template deployment tasks. This time, I will use “Deploy to Kubernetes” template, click on Apply.
3. In “Deploy to Kubernetes” task configuration, click “New” and create new service connection with your AKS under your Azure Subscription; input your desired namespace in Namespace (I have created a namespace called “dev” in AKS); input the kubectl command “set” in Command; input below content in Arguments of command.
image deployment/YOUR_K8S_DEPLOYMENT_NAME YOUR_K8S_POD_NAME=YOUR_ACR_NAME/YOUR_CONTAINER_NAME:$(Build.BuildId)
Expand the Secrets, select dockerRegistry in Type of secret; select Azure Container Registry in Container Registry type; select your Azure Subscription; select the of your ACR in Azure Container Registry; input K8S secret name in Secret name (for your AKS/K8S login into ACR).
4. Back to top, click “Pipeline” tab, click on the “Electric” icon in Artifacts. Check the “Enabled” box in Continuous deployment trigger. Then, finally, click “Save”.
Up to now, all the Build & Release Pipeline configuration in Azure DevOps has been done. You can either commit some update from local to Azure DevOps Repos to test end-to-end triggering flow or you can manual trigger Build Pipeline “sb-web-sample-01-docker-ado-Maven-CI” then it will trigger the Release Pipeline after build tasks are completed.
Finally, try to access your Web App URL which is sitting behind/protected by WAF (http://sample02.qooapps.net).
Hope you’re enjoying this article, this article should give you basic understanding for how to make Azure DevOps Build and Deploy Pipeline to work with Java Spring Boot, Maven, Docker (containerize) together with Azure cloud services (AKS, ACR, WAF). There are so much interesting Build & Deployment tasks can be added to enrich/enhance your DevOps workflows, e.g. Testing… Having sometime to further explore to make our life easier.
In next article, I’ll talk about Kubernetes orchestration…
- Making MEAN stack work with Azure DevOps
- Sample Java Web App in Spring Boot framework with Containerization
- Sample Java Spring Boot Web App with Containerization (variant to show TCP port change)
- Sample Java Web App in Spring Boot framework with Containerization (variant to show SSL)
- Sample Java Web App in Spring Boot framework with Containerization (with Oracle JRE 8 base image)
- Sample Java Web App in Spring Boot framework with Containerization (Plus Kubernetes NGINX Ingress Controller Deployment)