
Azure explained deep enough: Containers
Introduction
This is the second part of Azure mini-series Azure explained deep enough
Part1: Azure explained deep enough: learn and get certified
Part2: Azure explained deep enough: Containers <- this blog
Part3: Azure explained deep enough: Azure PaaS
Part4: Azure explained deep enough: Azure DevOps
Azure Container Instances
Containers are now a mature solution providing an additional level of infrastructure abstraction. In many cases, containers can replace workloads traditionally powered by virtual machines.
Wouldn’t it be nice to just “throw” a container to a cloud provider and say “Hey, here is my container, just make it work! ACI (Azure Container Instances) do just that! Other major cloud providers have similar offerings, with GCP Cloud Run or AWS Far Gate.
As with other blogs in this series, a companion repo with code is available here.
Prerequisites
If you would like to follow along, please make sure to have the following ready:
You can use Azure CLI on desktop or execute commands directly in Azure shell. Please read the first part of the series for more details.
Overview
In this Azure lesson, we will look at Azure Container Instances. What is the service about, what benefits it brings, how does the architecture look like and how to get started with a simple example.
Azure Container Instances is a compute offering that bridges the gap between lightweight Azure Functions and more complex, but fully-fledged Azure Kubernetes Service.

ACI is best suited for containerized workloads that can operate in isolation, simple apps, batch jobs including data science models, all kinds of tasks automation and integration scenarios.
- Fast startup: Launch containers in seconds.
- Per second billing: Incur costs only while the container is running.
- Hypervisor-level security: Isolate your application as completely as it would be in a VM.
- Custom sizes: Specify exact values for CPU cores and memory.
- Persistent storage: Mount Azure Files shares directly to a container to retrieve and persist state.
- Linux and Windows: Schedule both Windows and Linux containers using the same API.
Differences between ACI and Azure Functions
Here is an iconographic capturing the main differences between Azure Functions (Azure serverless offering which will be part of a later blog) and ACI.

The rule of thumb is, if you have an existing container, use ACI. If you need portability, use ACI.
Exercises
We are going to deploy a sample web page. The idea is that with docker CLI and ACI we can rapidly prototype, test and deploy directly from the docker command line!
Important note: this flow is only for testing purposes, in real code scenario you would have CI/CD pipeline deploying your app for you.
We are going to use bash with running docker daemon, but the same is of course possible with powershell
.
Docker CLI contains now build-in integration with Azure Container Instances through a context command. When using Azure CLI, you cat activate Azure Interactive by typing
_az interactive_
. This is an experimental feature of Azure CLI which gives you parameters completion and more!
Now let’s deploy a test container!
Create Azure Resource Group
Create a resource group for training purposes. You can use this script to quickly create or delete a resource group in Azure or use Azure Portal to do the same:
Or simply
az group create — name myResourceGroup — location location
Create Azure Container Registry
We will need Azure Container Registry to store our images, simple command will do it
az acr create — resource-group myResourceGroup \ — name myContainerRegistry — sku Basic
Deploy sample Web App
As a “warm-up” exercise, we are going to deploy a sample hello world web app.
- Run ACI hello-world image
az container create --resource-group your-resource-group --name learning-azure --image mcr.microsoft.com/azuredocs/aci-helloworld --dns-name-label aci-learing-blog --ports 80
- Great! Now show the FDQN address and use a browser to see the container running:
az container show --resource-group your-resource-group --name learning-azure --query "{FQDN:ipAddress.fqdn,ProvisioningState:provisioningState}" --out table
You should see “Welcome to Azure Container Instances!” as below. - Examine the container group in Azure
- Clean up resources
- Run
az container delete --resource-group your-resource-group --name learning-azure
to delete the container Running this command completely removes the container group so there are no charges.

Success!
Deploy sample Go API
Build docker container with Go API
docker build -t myContainerRegistry.azurecr.io/go-api:v1.0 .
A note on building the image here. We are using multi-stage builds to make image size smaller as well as distroless base image for Linux to lower potential attack surface. “Distroless” images contain only your application and its runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution. We are decorating the Dockerfile with commands outputting debug information for class while the image is being built. To do that, run the build command with --progress=plain
flag, like so
docker build --progress=plain -t myContainerRegistry.azurecr.io/go-api:v1.0 .
This will produce output from commands to stdout. Please read the comments in the Dockerfile for more information.
Another way to use a container is to run tests inside of it, this way you can test locally or in the pipeline without an explicit step in the pipeline. Build another image from a different file like so
docker build --progress=plain -f Dockerfile.test -t myContainerRegistry.azurecr.io/go-api:test .
Push the container to our registry
docker push myContainerRegistry.azurecr.io/go-api:v1.0
You might need to provide ACR username and password to start the container. Let’s capture them into variables (here are commands for Linux and Windows respectively)
Linux:
ACR_USERNAME=$(az acr credential show --resource-group your-resource-group --name myContainerRegistry--query username)ACR_PASSWORD=$(az acr credential show --resource-group your-resource-group --name myContainerRegistry --query passwords[0].value)
Windows:
$Env:ACR_USERNAME=$(az acr credential show --resource-group your-resource-group --name myContainerRegistry--query username) $Env:ACR_PASSWORD=$(az acr credential show --resource-group your-resource-group --name myContainerRegistry --query passwords[0].value)
Run go API container
az container create --registry-username $ACR_USERNAME --registry-password $ACR_PASSWORD --resource-group your-resource-group --name learning-azure-api --image myContainerRegistry.azurecr.io/go-api:v1.0 --dns-name-label learning-aci-api --ports 8080az container create --registry-username $Env:ACR_USERNAME --registry-password $Env:ACR_PASSWORD --resource-group your-resource-group --name learning-azure-api --image myContainerRegistry.azurecr.io/go-api:v1.0 --dns-name-label learning-aci-api --ports 8080
Now show the FDQN address and use a browser to see the container running:
az container show --resource-group your-resource-group --name learning-azure-api --query "{FQDN:ipAddress.fqdn,ProvisioningState:provisioningState}" --out table
- Obtain container IP and navigate to it appending
:8080/version
to call the API - Check container logs
az container logs --resource-group your-resource-group --name learning-azure-api
- Clean up resources
- Run
az container delete --resource-group your-resource-group --name learning-azure-api
to delete the container Running this command completely removes the container group so there are no charges.
We’ve seen how easy it is to deploy a container group directly to Azure Container Instances. This could be very useful for testing purposes and a quick inner development loop.
Conclusion
Containers are a powerful packaging and runtime mechanism, making cloud-native apps a reality. All major cloud providers offer a service to run containers seamlessly. We have seen how this can be done in Azure.
If you want to learn more, there are a lot of great blogs and tutorials to check if you are interested.