ACI is the simplest container platform on Azure. You can run single containers, or you can run multiple containers in a group to host a distributed application. There are different options for modelling the applications - you can use Azure’s YAML spec with the Azure CLI, or the Docker Compose spec with the Docker CLI.
In this lab we’ll use both options and see how ACI integrates with other Azure services.
Start by creating a Resource Group for the lab:
az group create -n labs-aci-compose --tags courselabs=azure -l eastus
The YAML model for ACI is a custom format which looks a bit like Bicep and a bit like Compose but isn’t either:
There are some specific details we need to include in this model:
localhost
You can pass this model to the Azure CLI when you create an ACI resource, and that will run all the containers in the model.
📋 Deploy the app with a container create
command and the file in labs/aci-compose/rng-aci-v1.yaml
.
Not sure how?</summary>
Check the help text:
az container create --help
You can supply a file
parameter and a name:
az container create -g labs-aci-compose -n rng-app --file labs/aci-compose/rng-aci-v1.yaml
</details>
Open the ACI resource in the Portal. Under Containers you should see the API and web containers both running. You can see the properties and logs for each container, and even connect to a shell session inside a container if you need to debug.
The YAML spec didn’t include a DNS name, but you’ll see there’s a public IP address we can use to try the app.
Browse to
http://<aci-ip-address>
and click the button - you should see a random number
The logs from the API container don’t give us much detail, but we can increase the logging level with a change to the model:
📋 Deploy the updated spec in labs/aci-compose/rng-aci-v2.yaml
. This is just a configuration change, how does ACI actually implement the update?
Not sure how?</summary>
Use the same container create command with the instance name and the updated spec:
az container create -g labs-aci-compose -n rng-app --file labs/aci-compose/rng-aci-v2.yaml
You’ll see the output Running...
for a while. The command recreates the containers and waits for the new ones to come online.
</details>
Check in the Events table for the containers in the Portal and you will see multiple entries for containers Started and entries for Killing the old containers.
You can’t change any properties of the compute environment for a running container. If you need to update environment variables, resource requests or ports then the only way to do that is by removing the old container and creating a replacement.
That’s true for all container runtimes - Docker, ACI and Kubernetes
ACI has its own YAML specification so you have access to all the features. If you don’t need ACI-specific configuration then you can model your app in a standard Docker Compose file instead and deploy to ACI with the Docker CLI.
The Compose model for the app is much simpler:
We can deploy to ACI using a docker compose
command, but first we need to set up a Docker Context so our local CLI is configured to talk to Azure (we covered this in the ACI lab):
docker login azure
docker context create aci labs-aci-compose --resource-group labs-aci-compose
docker context use labs-aci-compose
Now when you run docker
and compose
commands you’re working in the context of ACI in your lab resource group:
# this will show the containers you deployed with the az command:
docker ps
📋 Use the docker compose
command to bring the application up from the file labs/aci-compose/rng-compose-v1.yml
.
Not sure how?</summary>
It’s the usual up
command - you can specify a project name which becomes the ACI name:
docker compose -f labs/aci-compose/rng-compose-v1.yml --project-name rng-app-2 up -d
</details>
You’ll see output about the group being created, then the individual containers are created in parallel.
You can see your new containers in the Portal, or you can use the Docker command to print the details:
# for ACI containers the output includes the IP address:
docker ps
Browse to the new deployment and check the app is working. Open the container list in the Portal - you’ll see there are three even though we only define two in the model. What might the additional container be doing?
Create Storage Account:
az storage account create --sku Standard_ZRS -g labs-aci-compose -l westeurope -n <sa-name>
Get the connection string:
az storage account show-connection-string -g labs-aci-compose --query connectionString -o tsv -n <sa-name>
Use it to run a container locally with Blob Storage as the database:
# switch to the local Docker engine:
docker context use default
# be careful with the 'quotes' - they start at the key and end at the value:
docker run --name local -d -p 8013:80 -e 'ConnectionStrings__AssetsDb=<connection-string>' courselabs/asset-manager:22.11
Browse to http://localhost:8013 and you’ll see some data on the screen. Open your Blob Storage container in the Portal and there’s the raw data, uploaded from your local container.
The container also writes a file to local storage - this doesn’t really do anything, but it uses the container name as the filename:
# list the contents of the folder in the container:
docker exec local ls /app/lockfiles
An ACI container can access Blob Storage using the same code, and you can also mount an Azure Files share in ACI. The share appears as part of the container filesystem, but when the app writes data there it’s actually stored in the share.
📋 Create a file share called assetmanager
in your Azure Storage Account and print the Storage Account key.
Not sure how?</summary>
We did this in the Azure Files lab:
# create the share:
az storage share create -n assetmanager --account-name <sa-name>
# print the key:
az storage account keys list -g labs-aci-compose --query "[0].value" -o tsv --account-name <sa-name>
</details>
Edit the file assetmanager-aci.yaml:
<sa-name>
and <sa-key>
with your own Storage Account name and key<connection-string>
with your Storage Account connection stringThen deploy a new ACI group to run the Asset Manager container using Blob Storage and Files:
az container create -g labs-aci-compose --file labs/aci-compose/assetmanager-aci.yaml
Browse to the app when it’s running. Can you find the lock file in your Storage Account?
ACI is meant to be a quick and easy solution for running containers in the cloud. It’s reliable because it will restart containers if they fail, but it doesn’t have a feature to let you scale horizontally. Run another copy of the Asset Manager app in ACI. Do they both write to the same file share? How would you load-balance traffic between them?
You can delete the RG for this lab to remove all the resources, including the containers you created with the Docker CLI:
az group delete -y --no-wait -n labs-aci-compose
Now change your Docker context back to your local Docker Desktop, and remove the lab context:
docker context use default
docker context rm labs-aci-compose