Publishing multi-container application via docker compose in Azure
Goal:
The goal is to take a standard docker-compose file that works on a local docker instance and have it run in Azure. This general write-up assumes you have a docker-compose file that is pulling images from a private azure container registry. The Microsoft documentation on how to push your images to the registry and modify your docker-compose to pull from them is good. The Microsoft tutorial Deploy a multi-container group using Docker Compose is very helpful for creating a registry, pushing your images, and modifying your docker-compose file. From the section on creating an Azure context and beyond it doesn't appear to be a good guide for actually running applications in Azure.
The Azure ACI commands work to push images to a private container registery but they do not create a useful containerized application as they shut down since there are no active running tasks. That means trying azure container groups which have a reset policy. Something Azure seems to care deeply about.
For containerapps, you have to piece it together from their documentation.
https://learn.microsoft.com/en-us/cli/azure/containerapp/compose?view=azure-cli-latest
Spin up your containers
az containerapp compose
Prerequisites:
* You need a resource group created
1. Register the app
az provider register -n Microsoft.App --wait
2. Create the containerapp
az containerapp compose create -g muserdemo --environment muserdocker --compose-file-path ./docker-compose.yml
This will put the containers up and start them but will complain that the azure file storage mount setup in docker compose is invalid with containerapps. So you then have to mount storage in a separate method. In the older ACI documentation the docker-compose mounts work great, but not with container apps.
Setting Up Storage
Storage Commands - https://learn.microsoft.com/en-us/azure/container-apps/storage-mounts?pivots=azure-cli
and a tutorial that I found very helpful - https://learn.microsoft.com/en-us/azure/container-apps/storage-mounts-azure-files?tabs=bash
3. Setup environment variables for the next commands
RESOURCE_GROUP="muserdemo"
ENVIRONMENT_NAME="muserdemo-storage-environment"
LOCATION="West US 2"
4. Make sure the latest az extensions are loaded on your box
az extension add -n containerapp --upgrade
5. Register the namespace
az provider register --namespace Microsoft.App
6. Register the OperationalInsights
az provider register --namespace Microsoft.OperationalInsights
7. One more environment variable before creating the storage account
STORAGE_ACCOUNT_NAME="mymuserdemostorageacct$RANDOM"
az storage account create --resource-group $RESOURCE_GROUP --name $STORAGE_ACCOUNT_NAME --location "$LOCATION" --kind StorageV2 --sku Standard_LRS --enable-large-file-share --query provisioningState
8. More environment variables
STORAGE_SHARE_NAME="muserwebdata"
9. Create the volume share
az storage share-rm create --resource-group $RESOURCE_GROUP --storage-account $STORAGE_ACCOUNT_NAME --name $STORAGE_SHARE_NAME --quota 1024 --enabled-protocols SMB --output table
10. Create environment varaiables and then link the storage to the container
ENVIRONMENT_NAME="muserdocker"
STORAGE_ACCOUNT_KEY=`az storage account keys list -n $STORAGE_ACCOUNT_NAME --query "[0].value" -o tsv`
az containerapp env storage set --access-mode ReadWrite --azure-file-account-name $STORAGE_ACCOUNT_NAME --azure-file-account-key $STORAGE_ACCOUNT_KEY --azure-file-share-name $STORAGE_SHARE_NAME --storage-name $STORAGE_MOUNT_NAME --name $ENVIRONMENT_NAME --resource-group $RESOURCE_GROUP --output table
11. Export the config of the container to yaml to work with az container commands
az containerapp show --name apache --resource-group muserdemo --output yaml > app.yaml
I renamed app.yaml as apache-app.yaml for updating the config as I also have a php container and mariadb container.
You end up modifying the exported yaml file to tell it where the storage that you created above resides. You have to do this for each container that you want persistent storage. For my use case, I could use the same storage for my PHP and Apache containers but needed to make a new mount for MariaDB.
12. Set another environment variable for the command to update your container
CONTAINER_APP_NAME="apache"
az containerapp update --name $CONTAINER_APP_NAME --resource-group $RESOURCE_GROUP --yaml app.yaml --output table
13. Login via docker exec and verify the container is mounted as you expect
az containerapp exec --name $CONTAINER_APP_NAME --resource-group $RESOURCE_GROUP