Re-deploy your containerized Java application on Azure

In my previous post a while ago I showed you how to deploy your dockerized Java application on Azure. It was a step-by-step introduction switching from browser to IDE, to command line (Docker CLI or Azure CLI), to the Azure web interface. It worked out, but regarding that it was just about the deployment of your code it took quite some time, right? So what about re-deploying your application maybe after making small changes, like fixing a tiny bug? Do you want to do those steps

-> change your code
-> re-build your project
-> build a new docker image
-> tag the image correctly
-> push it to your remote repo
-> stop the running container (?)
-> re-deploy the new container to Azure

over and over again? No, certainly not!

You just want to change the piece of code and then run the following steps as automated as possible. Switching from one tool to another is also not what you want. There are faster ways to achieve this than executing all those steps by hand, depending on your actual environment and personal preferences. So as a Java developer you will most likely build your project with Gradle or Maven. This comes in handy as they offer great plugins to make your life easier. In the following I will stick to Gradle, however similar things are possible using Maven.

My goal was to see how far I could possibly push the whole build and deployment process.

Generate and authenticate to your Azure resources

If you have the Azure resources (resource group and container registry) still available from my previous tutorial you can use them. However, you should get into the habit of removing resources you don’t need anymore to not accidentally produce costs. Thats why I also want to show here how you can create the needed resources using the Azure CLI instead of the Azure portal. Like in my last post you need to log in, create a resource group and container registry.

az login
az group create 
  --name DeployJava_RG 
  --location westeurope
az acr create 
  --name deployregistry 
  --resource-group DeployJava_RG 
  --sku Basic 
  --admin-enabled true

The docker deamon needs access to the registry that was just created. To avoid having to provide the credentials in future steps you need to log in first. To get the auto-generated password, do

az acr credential show 
  --resource-group DeployJava_RG 
  --name deployregistry

Use the password displayed in the output to log in during the next step.

docker login deployregistry.azurecr.io --username deployregistry

After these steps you should be able to directly push your docker images to your Azure registry. Keep in mind, after a certain time you may have to log in again. Storing these commands will not only speed up future deployments, but will also allow you to rebuild your application in a more reproducible way than using the Azure web interface.

Just Jib-it

As an example I chose the same project as in my previous post. You can use jib to add an additional task to your usual Gradle build process. When invoked, the Gradle plugin creates a new Docker image out of your project without you having to write a Dockerfile! In addition, it also allows you to directly push the new image to a registry of your choice, for example your Azure repository. If you followed through the previous steps you don’t need to provide credentials. If you didn’t, you need to make them available from somewhere else.

  • A ‘Credential helper tool’ that can provide credentials for various registries
  • Define specific credentials stored i.e. within gradle.properties

The following shows the code I added to the existing gradle.build. This is a working example using the Azure CLI authentication method.

plugins {
        ...
id 'com.google.cloud.tools.jib' version '2.2.0'
        ...
}

jib {
	from {
		image = 'openjdk:8-alpine'
	}
	to {
		image = 'deployregistry.azurecr.io/my_image'

		/*   *** with authentification ***

                *** using credential helper tools ***
                credHelper = 'gcr'

                *** using specific credentials ***
                auth {
                      Username: azureUsername
                      Password: azurePwd 
	            }
       */
        }
	container {
		ports = ['8085']
		creationTime = 'USE_CURRENT_TIMESTAMP'
	}
}
tasks.build.dependsOn tasks.jib

This way your new Docker image will be pushed to your Azure registry with each new Gradle build.

Well we managed to wrap up the first steps quite easily. Leaving us with handling the actual (re-)deployment within the cloud. There are now several options depending on what you actually want to do. You can deploy a container instance (like in my previous post) or you can run your code as an actual web app with Azure Web Service. Using this service adds further possibilities regarding deployment, scaling and load balancing of your application. In the next sections I will show you how to deploy both options.

Deploy the container instance (ACI)

To have the link to my last post I will show you how to (re-)deploy you docker image as a container instance. As for the ‘Azure Portal’ it is basically one step to deploy it

az container create 
 --resource-group DeployJava_RG 
 --name deployedjavacode
 --image deployregistry.azurecr.io/my_image
 --ip-address public
 --ports 8085
 --dns-name-label my_app
 --registry-username deployregistry

Your application should now be running on

https://my_app/westeurope/azurecontainer.io:8085/azure/docker/hello

To redeploy after you changed and rebuild your project, which included ‘jibbing‘ it, do:

az container restart 
  --name deployedjavacode 
  --resource-group DeployJava_RG

Deploy your code as a web app

Instead of running a single container instance you can also choose ‘App Service’ provided by Azure. That’s why I want to present it here as well. As in the previous section you can deploy your web app using the Azure CLI. However, I found a much more appealing way using yet another Gradle plugin. Using this option really allows me to do what I intended. Making the redeployment of my code a ‘one-liner’!

To actually achieve this we need to prepare only one more thing. The plugin allows us to create the necessary AppServicePlan as well as deploying the web app from a repository containing the Docker image. However, to do this it will also require access to the registry. This can directly be implemented within the plugin. The service needs to be provided with the access using a Azure SDK auth file. The file contains the information to assign the service the role as service principal and configures it with the access to the resources within the subscription. Sounds complicated but can be done with the following command

az ad sp create-for-rbac --sdk-auth > my.azureauth

Now we only need to add and configure the plugin to deploy the web app on Azure. The following code needs to be added to build.gradle. It basically contains all the input needed by Azure. In addition to the automation, this also provides good documentation.

plugins {
        ...
	id 'com.google.cloud.tools.jib' version '2.2.0'
	id 'lenala.azure.azurewebapp' version '1.0'
        ...

}

azureWebApp{
	resourceGroup = 'DeployJava_RG'
	appServicePlanName='deployingJava'
	appName = 'deployedJavaApp'
	stopAppDuringDeployment = true
	pricingTier = 'B1'
	region = 'westeurope'
	appService = {
		type = 'docker'
		imageName = 'deployregistry.azurecr.io/my_image'
	}
	authentication = {
		type = 'file'
		file = 'my.azureauth'
	}
	deployment = {
		type = 'none'
	}
}

Finally, we have prepared everything necessary. If we did everything the right way, to deploy or redeploy our web app on Azure is only one step. We only need to touch our code while building and deployment is enabled with a single line.

gradle clean build azureWebappDeploy

So we really achieved what we set out for:

-> change your code
/*
-> re-build your project
-> build a new docker image
-> tag the image correctly
-> push it to your remote repo
-> stop the running container (?)
*/

-> re-deploy the new container to Azure

If you care about the cost, make sure you delete the services you don’t need anymore.

az group delete --name DeployJava_RG

I hope you could follow along and found it useful. Stay tuned for further posts to come!

Views All Time
378
Views Today
1
Short URL for this post: https://blog.oio.de/Q3x72
This entry was posted in Java Runtimes - VM, Appserver & Cloud and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *