Azure Hands-On - Azure Container Instances (ACI)
Azure Learning Path for Cloud and DevOps Engineers
Table of contents
- 📝Introduction
- 📝Log in to the Azure Management Console
- 📝Prerequisites:
- 📝Setting an Azure Storage Account to Load Bash or PowerShell
- 📝Create an Azure Container Instance
- 📝Run a container to completion
- 📝Deploy Azure Cosmos DB
- 📝Deploy a container that works with CosmoDB
- Use secured environment variables to hide connection information
- 📝Create an Azure file share
- 📝Get storage credentials
- 📝Deploy a container and mount the file share
- 📝Troubleshoot Azure Container Instances
- Get logs from your prior deployed container instance
- Get container events
- Execute a command in our container
- Monitor CPU and memory usage on our container
📝Introduction
In this hands-on lab, we walked through the use of Azure Container Instances(ACI) which let us run a container in Azure without managing virtual machines and without a higher-level service.
Learning objectives:
Run containers in Azure Container Instances.
Control what happens when your container exits.
Use environment variables to configure your container when it starts.
Attach a data volume to persist data when your container exits.
Learn some basic ways to troubleshoot issues on your Azure containers.
📝Log in to the Azure Management Console
Using your credentials, make sure you're using the right Region. In my case, I am using the region eastus
in my Cloud Playground Sandbox.
📌Note: You can also use the VSCode tool or from your local Terminal to connect to Azure CLI
More information on how to set it up is at the link.
📝Prerequisites:
Update to PowerShell 5.1, if needed.
Install .NET Framework 4.7.2 or later.
Visual Code
Web Browser (Chrome, Edge)
Azure CLI installed
Azure subscription
Docker installed
📝Setting an Azure Storage Account to Load Bash or PowerShell
- Click the Cloud Shell icon
(>_)
at the top of the page.
- Click PowerShell.
- Click Show Advanced Settings. Use the combo box under Cloud Shell region to select the Region. Under Resource Group and Storage account(It's a globally unique name), enter a name for both. In the box under File Share, enter a name. Click ***Create storage (***if you don't have any yet).
📝Create an Azure Container Instance
Sign in to the Azure portal with your Azure subscription.
You can use the
Open Azure Cloud Shell
from the Azure portal by selecting theCloud Shell
icon or use another tool to use theAzure CLI
bash environment.Create a new resource group
<resource_group_name>
so that it's easier to clean up these resources when you're finished with the lab. Remember it for the rest of the exercises in this lab you will use the same RG. You also need to choose a region in which you want to create the resource group; for example,East US
.az group create --name <resource_group_name> --location <region>
Create a container by providing a name, a Docker image, and an Azure resource group to the
az container create
command. You can optionally expose the container to the Internet by specifying a DNS name label. In this example, deploy a container that hosts a small web app. You can also select the location to place the image; we use theEast US
region, but you can change it to a location close to you.Provide a DNS name to expose your container to the Internet. Your DNS name must be unique. For learning purposes, run this command to create a
Bash
variable that holds a unique name:DNS_NAME_LABEL=aci-demo-$RANDOM
Run the following
az container create
command to start a container instance:az container create \ --resource-group <resource_group_name> \ --name <name_container> \ --image mcr.microsoft.com/azuredocs/aci-helloworld \ --ports 80 \ --dns-name-label $DNS_NAME_LABEL \ --location eastus
$DNS_NAME_LABEL
specifies your DNS name. We are using a sample imageazuredocs/aci-helloworld
, refers to a container image hosted on Microsoft Container Registry that runs a basicNode.js
web application.When the
az container create
command completes, runaz container show
to check its status:az container show \ --resource-group <resource_group_name> \ --name <name_container> \ --query "{FQDN:ipAddress.fqdn,ProvisioningState:provisioningState}" \ --output table
You get your container's fully qualified domain name (FQDN) and its provisioning state. Here's an example:
If your container is in the Creating state, wait a few moments, and run the command again until you see the Succeeded state.
From a browser, go to your container's FQDN to see it running. Ensure you enter the
http://
prefix in front of theaci-demo
... string. You should get this welcome page:
📝Run a container to completion
With a configurable restart policy, you can specify that your containers are stopped when their processes have been completed.
Azure Container Instances has three restart-policy options:
Restart policy | Description |
Always | Containers in the container group are always restarted. This policy makes sense for long-running tasks like a web server. This setting is the default applied when no restart policy is specified at container creation. |
Never | Containers in the container group are never restarted. The containers run one time only. |
OnFailure | Containers in the container group are restarted only when the process executed in the container fails (when it terminates with a nonzero exit code). The containers are run at least once. This policy works well for containers that run short-lived tasks. |
To create a container instance, we are using a sample image from the azuredocs/aci-wordcount
container image and specify the OnFailure
restart policy. This container refers to a container image hosted on Microsoft Container Registry that runs a Python script that analyzes the text of Shakespeare's Hamlet, writes the 10 most common words to standard output, and then exits.
Run this
az container create
command to start the container:az container create \ --resource-group <resource_group_name> \ --name <name_container> \ --image mcr.microsoft.com/azuredocs/aci-wordcount:latest \ --restart-policy OnFailure \ --location eastus
Azure Container Instances starts the container and then stops it when its process (a script, in this case) exits. When Azure Container Instances stops a container whose restart policy is Never or OnFailure, the container's status is set to
Terminated
.Run
az container show
to check your container's status:az container show \ --resource-group <resource_group_name> \ --name <name_container> \ --query "containers[0].instanceView.currentState.state"
Repeat the command until it reaches the
Terminated
status.Run
az container logs
to view the container's logs to examine the output:az container logs \ --resource-group <resource_group_name> \ --name <name_container>
📝Deploy Azure Cosmos DB
Environment variables allow us to dynamically configure the application or script the container runs. We can use the Azure CLI, PowerShell, or the Azure portal
to set variables when you create the container. Secured environment variables prevent sensitive information from displaying in the container's output.
Let's create an Azure Cosmos DB instance and use environment variables to pass the connection information to an Azure container instance. An application in the container uses the variables to write and read data from Azure Cosmos DB. We will create both an environment variable and a secured environment variable so that we can see the difference between them.
Create an Azure Cosmos DB, providing a unique database name. For learning purposes, run this command in Cloud Shell to create a Bash variable that holds a unique name:
COSMOS_DB_NAME=aci-cosmos-db-$RANDOM
Run this
az cosmosdb create
command to create your Azure Cosmos DB instance:COSMOS_DB_ENDPOINT=$(az cosmosdb create \ --resource-group <resource_group_name> \ --name $COSMOS_DB_NAME \ --query documentEndpoint \ --output tsv)
This command can take a few minutes to complete.
$COSMOS_DB_NAME
specifies your unique database name. The command prints the endpoint address for your database. Here, the command saves this address to the Bash variableCOSMOS_DB_ENDPOINT
.Run
az cosmosdb keys list
to get the Azure Cosmos DB connection key and store it in a Bash variable namedCOSMOS_DB_MASTERKEY
:COSMOS_DB_MASTERKEY=$(az cosmosdb keys list \ --resource-group <resource_group_name> \ --name $COSMOS_DB_NAME \ --query primaryMasterKey \ --output tsv)
📝Deploy a container that works with CosmoDB
Create an Azure container instance that can read from and write records to our Azure Cosmos DB instance.
The two environment variables you created previously, COSMOS_DB_ENDPOINT
and COSMOS_DB_MASTERKEY
, hold the values you need to connect to the Azure Cosmos DB instance.
Run the following
az container create
command to create the container:az container create \ --resource-group <resource_group_name> \ --name <name_container> \ --image mcr.microsoft.com/azuredocs/azure-vote-front:cosmosdb \ --ip-address Public \ --location eastus \ --environment-variables \ COSMOS_DB_ENDPOINT=$COSMOS_DB_ENDPOINT \ COSMOS_DB_MASTERKEY=$COSMOS_DB_MASTERKEY
azuredocs/azure-vote-front:cosmosdb
refers to a container image that runs a fictitious voting app.Note the
--environment-variables
argument. This argument specifies environment variables that are passed to the container when the container starts. The container image is configured to look for these environment variables. Pass the name of the Azure Cosmos DB endpoint and its connection key.Run the
az container show
command to get your container's public IP address:az container show \ --resource-group <resource_group_name> \ --name <name_container> \ --query ipAddress.ip \ --output tsv
In a browser, go to your container's IP address.
📌Note: Sometimes containers take a minute or two to fully start and be able to receive connections. If there's no response when you go to the IP address in your browser, wait a few moments and refresh the page.
Once the app is available, you get this page:
Use secured environment variables to hide connection information
Let's learn how to prevent sensitive information.
Let's start by seeing the current behavior in action. Run the following
az container show
command to display your container's environment variables:az container show \ --resource-group <resource_group_name> \ --name <name_container> \ --query containers[0].environmentVariables
Although these values don't appear to your users through the voting application, it's a good security practice to ensure that sensitive information (such as connection keys) isn't stored in plain text.
Secure environment variables prevent clear text output. To use secure environment variables, use the
--secure-environment-variables
argument instead of the--environment-variables
argument.Run the following command to create a second container that makes use of secured environment variables:
az container create \ --resource-group <resource_group_name> \ --name <name_container> \ --image mcr.microsoft.com/azuredocs/azure-vote-front:cosmosdb \ --ip-address Public \ --location eastus \ --secure-environment-variables \ COSMOS_DB_ENDPOINT=$COSMOS_DB_ENDPOINT \ COSMOS_DB_MASTERKEY=$COSMOS_DB_MASTERKEY
Note the use of the
--secure-environment-variables
argument.Run the following
az container show
command to display your container's environment variables:az container show \ --resource-group <resource_group_name> \ --name <name_container> \ --query containers[0].environmentVariables
This time, we can see that your environment variables don't appear:
The values of your environment variables don't appear at all. That's OK because these values refer to sensitive information.
📝Create an Azure file share
Azure Container Instances are stateless. If the container crashes or stops, all of its state is lost. To persist state
beyond the lifetime of the container, we must mount a volume from an external store.
We will mount an Azure file share to an Azure container instance so that we can store data and access it later.
Let's create a storage account and a file share. Later, we can make the file share accessible to an Azure container instance.
Our storage account requires a unique name. For learning purposes, run the following command to store a unique name in a Bash variable:
STORAGE_ACCOUNT_NAME=demostorageaccount$RANDOM
Run the following
az storage account create
command to create your storage account:az storage account create \ --resource-group <resource_group_name> \ --name $STORAGE_ACCOUNT_NAME \ --sku Standard_LRS \ --location eastus
Run the following command to place the storage account connection string into an environment variable named
AZURE_STORAGE_CONNECTION_STRING
:export AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string \ --resource-group <resource_group_name> \ --name $STORAGE_ACCOUNT_NAME \ --output tsv)
AZURE_STORAGE_CONNECTION_STRING
is a special environment variable that the Azure CLI understands. Theexport
part makes this variable accessible to other CLI commands that you run later.Run this command to create a file share in the storage account:
az storage share create --name <name_share>
📝Get storage credentials
To mount an Azure file share as a volume in Azure Container Instances, we need these three values:
Storage account name
Share name
Storage account access key
We already have the first two values. The storage account name is stored in the STORAGE_ACCOUNT_NAME
Bash variable. We specified a share name in the previous step. Here, we get the remaining value: the storage account access key.
Run the following command to get the storage account key:
STORAGE_KEY=$(az storage account keys list \ --resource-group <resource_group_name> \ --account-name $STORAGE_ACCOUNT_NAME \ --query "[0].value" \ --output tsv)
The result is stored in a Bash variable named
STORAGE_KEY
.As an optional step, print the storage key to the console.
echo $STORAGE_KEY
📝Deploy a container and mount the file share
To mount an Azure file share as a volume in a container, we specify the share and volume mount point when we create the container.
Run this
az container create
command to create a container that mounts/aci/logs/
to our file share. This container refers to a simple container image hosted on Microsoft Container Registry that runsNode.js
application showing how to interact with mounted Azure Files volumes from Azure Container Instances.az container create \ --resource-group <resource_group_name> \ --name <name_container> \ --image mcr.microsoft.com/azuredocs/aci-hellofiles \ --location eastus \ --ports 80 \ --ip-address Public \ --azure-file-volume-account-name $STORAGE_ACCOUNT_NAME \ --azure-file-volume-account-key $STORAGE_KEY \ --azure-file-volume-share-name <name_share> \ --azure-file-volume-mount-path /aci/logs/
Run
az container show
to get our container's public IP address:az container show \ --resource-group <resource_group_name> \ --name <name_container> \ --query ipAddress.ip \ --output tsv
From a browser, navigate to our container's IP address.
Enter some text into the form, and select
Submit
. This action creates a file that contains the text you entered in the Azure file share.Run this
az storage file list
command to display the files that are contained in our file share:az storage file list -s <name_share> -o table
Run
az storage file download
to download a file to our Cloud Shell session. Replace <filename> with one of the files that appeared in the previous step:az storage file download -s <name_share> -p <filename>
Run the
cat
command to print the contents of the file.cat <filename>
Remember that our data persists when our container exits. We can mount our file share to other container instances to make that data available to them.
📝Troubleshoot Azure Container Instances
To help the understanding, here are some basic ways to troubleshoot container instances:
Pulling container logs
Viewing container events
Attaching to a container instance
Get logs from your prior deployed container instance
- Run the following
az container logs
command to see the output from the cats and dogs voting app container you created in the prior exercise:
az container logs \
--resource-group <resource_group_name> \
--name <name_container> \
Get container events
The az container attach
command provides diagnostic information during container startup. Once the container has started, it also writes standard output and standard error streams to our local terminal.
Run
az container attach
to attach to your container:az container attach \ --resource-group <resource_group_name> \ --name <name_container> \
📌Note: Enter <kbd>Ctrl+C</kbd>
to disconnect from our attached container.
Execute a command in our container
We may need to run commands directly on our running containers for diagnoses and troubleshooting purposes.
To see commands in our container, run the following
az container exec
command to start an interactive session on our container:az container exec \ --resource-group <resource_group_name> \ --name <name_container> \ --exec-command /bin/sh
At this point, you're effectively working inside the container.
Run a command.
You can explore the system further if you wish. When you're done, run the
exit
command to stop the interactive session.
Monitor CPU and memory usage on our container
See how to monitor CPU and memory usage on our container.
Run the following
az container show
command to get the ID of our Azure container instance and store the ID in a Bash variable:CONTAINER_ID=$(az container show \ --resource-group <resource_group_name> \ --name <name_container> \ --query id \ --output tsv)
Run the
az monitor metrics list
command to retrieve CPU usage information:az monitor metrics list \ --resource $CONTAINER_ID \ --metrics CPUUsage \ --output table
Note the
--metrics
argument. Here, CPU Usage specifies to retrieve CPU usage.Run this
az monitor metrics list
command to retrieve memory usage information:az monitor metrics list \ --resource $CONTAINER_ID \ --metrics MemoryUsage \ --output table
Here, you specified MemoryUsage for the
--metrics
argument to retrieve memory usage information.
In the Azure portal, Azure Container Instances CPU and memory usage information look like this:
📌Note - At the end of each hands-on Lab, always clean up all resources previously created to avoid being charged.
Congratulations — you have completed this hands-on lab covering the basics of Azure Container Instances (ACI), running containers in Azure without managing virtual machines and without a higher-level service.
Thank you for reading. I hope you understood and learned something helpful from my blog.
Please follow me on Cloud&DevOpsLearn and LinkedIn, franciscojblsouza