Container Instances
Azure Container Instances (ACI) are good for scenarios that operate in isolated containers. For example: simple apps, task automation or build jobs. Benefits:
Fast startup
Can start in seconds without having to manage a VMInternet access
Allows exposing your container with an IP and FQDNHypervisor
VM-level isolationCustom specs
Optimum utilisation by allowing exact CPU and memory specificationsPersistent storage
Via Azure File shares mountsLinux and Windows support
Schedule Linux and Windows containers in one API
Resources
Container group
A collection of containers deployed on the same host machine. Similar to a k8s pod.Container
Only Linux is suppported for multi-container groups. Windows only supports a single container deployment.
Deployment
You can deploy with a resource manager template or a YAML file.
- Resource manager template preferred when deploying other resources alongside your ACI
- YAML preferred when only deploying ACI (since it is more concise)
When deploying, Azure allocates resources to your group by adding up the requested resources for each container within the group.
Networking
Port mapping is not supported. Public ports cannot be different from the container port defined via EXPOSE. Containers within a group can reach each other via localhost on their container ports.
Storage
You can mount external volumes within a container group into specific paths within the individual containers. Supported volumes incude:
- Azure file share
- Secrets
- emptyDir (for caching and temp storage)
- gitDir
CLI
deploy
az container create \
--resource-group myResourceGroup \
--name mycontainer \
--image mcr.microsoft.com/azuredocs/aci-helloworld \
--ports 80 \
--dns-name-label aci-example-21011 --location myLocation \
--os-type Linux \
--cpu 1 \
--memory 1.5
verify
az container show \
--resource-group myResourceGroup \
--name mycontainer \
--query "{FQDN:ipAddress.fqdn,ProvisioningState:provisioningState}" \
--out table
Restart policies
Because ACIs are so quick and easy to deploy (and they are billed by the second), they provide an ideal solution to run-once tasks like, for example, image rendering. Restart policies allow you to specify when a container should be restarted to support this workflow.
AlwaysNeverOnFailure
Selecting the OnFailure restart policy will allow a containerised script to run, restart if it failed, then exit without restarting on completion.
Environment variables
Similar to --env for docker run. Secure values are supported for both Windows and Linux for secrets.
az container create \
--resource-group myResourceGroup \
--name mycontainer2 \
--image mcr.microsoft.com/azuredocs/aci-wordcount:latest
--restart-policy OnFailure \
--environment-variables 'NumWords'='5' 'MinLength'='8'
Secure values
Secure values are intended for sensitive information. Using secure values is safer than including them in your container image. Secure values are only accessible from within your container, they are not present in the container's properties on Azure.
You can use a YAML deployment file to specify secure values.
apiVersion: 2018-10-01
location: eastus
name: securetest
properties:
containers:
- name: mycontainer
properties:
environmentVariables:
- name: 'NOTSECRET'
value: 'my-exposed-value'
- name: 'SECRET'
secureValue: 'my-secret-value'
image: nginx
ports: []
resources:
requests:
cpu: 1.0
memoryInGB: 1.5
osType: Linux
restartPolicy: Always
tags: null
type: Microsoft.ContainerInstance/containerGroups
Deploying like so:
az container create \
--resource-group myResourceGroup \
--file secure-env.yaml \
Mounts
By default, ACIs are stateless. If the container stops for any reason then all state is lost. To persist state longer than the lifetime of the container, you can mount a volume from an external store.
Limitations
- Only Linux support
- Only Common Internet File System (CIFS) support
A more modern variant of SMB. - Must run container as root
Deploying with a mount
az container create \
--resource-group $ACI_PERS_RESOURCE_GROUP \
--name hellofiles \
--image mcr.microsoft.com/azuredocs/aci-hellofiles \
--dns-name-label aci-demo \
--ports 80 \
--azure-file-volume-account-name $ACI_PERS_STORAGE_ACCOUNT_NAME \
--azure-file-volume-account-key $STORAGE_KEY \
--azure-file-volume-share-name $ACI_PERS_SHARE_NAME \
--azure-file-volume-mount-path /aci/logs/
apiVersion: '2019-12-01'
location: eastus
name: file-share-demo
properties:
containers:
- name: hellofiles
properties:
environmentVariables: []
image: mcr.microsoft.com/azuredocs/aci-hellofiles
ports:
- port: 80
resources:
requests:
cpu: 1.0
memoryInGB: 1.5
volumeMounts:
- mountPath: /aci/logs/
name: filesharevolume
osType: Linux
restartPolicy: Always
ipAddress:
type: Public
ports:
- port: 80
dnsNameLabel: aci-demo
volumes:
- name: filesharevolume
azureFile:
sharename: acishare
storageAccountName: <Storage account name>
storageAccountKey: <Storage account key>
tags: {}
type: Microsoft.ContainerInstance/containerGroups
Deploying multiple mounts
In order to deploy with multiple mounted volumes, you have to use a YAML or Azure Resource Manager template deployment.
# ...
properties:
# ...
# volume declarations appear in top-level properties
volumes:
- name: volume1
azureFile:
sharename: acishare1
storageAccountName: <Storage account name>
storageAccountKey: <Storage account key>
- name: volume2
azureFile:
sharename: acishare2
storageAccountName: <Storage account name>
storageAccountKey: <Storage account key>
# ...
# then those volumes are mounted inside individual container properties
containers:
- name: multiplemounts
properties:
# ...
volumeMounts:
- mountPath: /mnt/share1/
name: volume1
- mountPath: /mnt/share2/
name: volume2
ARM template is similar:
// in properties:
"volumes": [{
"name": "myvolume1",
"azureFile": {
"shareName": "share1",
"storageAccountName": "myStorageAccount",
"storageAccountKey": "<storage-account-key>"
}
},
{
"name": "myvolume2",
"azureFile": {
"shareName": "share2",
"storageAccountName": "myStorageAccount",
"storageAccountKey": "<storage-account-key>"
}
}]
And in the container definition:
// in containers[].properties:
"volumeMounts": [{
"name": "myvolume1",
"mountPath": "/mnt/share1/"
},
{
"name": "myvolume2",
"mountPath": "/mnt/share2/"
}]