Azure Container Registry
- A managed, private Docker registry service
- Create and maintain container registries to store and manage private Docker container images
- Automate building of container images with triggers such as source code commits and base image updates
- Use cases:
- Scalable orchestration systems managing containerised applications across clusters of hosts (Kubernetes, DC/OS, Docker Swarm)
- Azure services that support building and running applications at scale (Azure Kubernetes Service, App Service, Batch, Service Fabric)
- Service tiers:
- Basic:
- Same programmatic capabilities as the other tiers
- Storage and image throughput are most appropriate for lower usage scenarios
- Standard:
- Offer same capabilities as the Basic plan, with increased storage and image throughput
- Should satisfy the needs of most production scenarios
- Premium:
- Provides the highest amount of storage and concurrent operations, enabling high-volume scenarios
- Adds features such as geo-replication for multi-region management for a single registry, content trust for image tag signing and a private link with private endpoints to restrict access to the registry
- Basic:
Storage Capabilities
- All tiers benefit from encryption-at-rest for image data security and geo-redundancy for image data protection
- Encryption-at-rest: All container images and other artifacts in your registry are encrypted before being stored and descrypted when pulled
- Regional storage: Stores data in the registry's region to help customers meet data residency and compliance requirements
- Geo-replication: Helps guard against losing access to youre registry in a regional failure event
- Zone redundancy: A Premium tier feature, zone redundancy uses availability zones to replicate your registry to a minimum of three separate zones in each enabled region
- Scalable storage: Allows you to create as many repositories, images, layers or tags as you need up to the registry storage limit
- You should periodically delete unused repositories, tags and images to maintain performance of your registry
Building and Managing Containers with Tasks
- Scenarios:
- Quick task: Build and push a single container image to a registry on-demand (docker build, docker push)
- Automatically triggered tasks: Trigger on source code update, base image update or schedule
- Multi-step tasks: Extend the single image build-and-push capability of tasks with multi-step, multi-container-based workflows
Elements of a Dockerfile
- A Dockerfile is a script containing a series of instructions used to build a Docker image, usually containing the following:
- Base or parent image to create the new image
- Commands to update the base OS and install other software
- Build artifacts to include (ex. applications)
- Services to expose (ex. storage and network configurations)
- Command to run when the container is launched
- Creating a dockerfile involves choosing a base image that serves as the foundation for your application
- Ex. for a .NET application, you might choose a Microsoft .NET base image
# Use the .NET 6 runtime as a base image FROM mcr.microsoft.com/dotnet/runtime:6.0 # Set the working directory to /app WORKDIR /app # Copy the contents of the published app to the container's /app directory COPY bin/Release/net6.0/publish/ . # Expose port 80 to the outside world EXPOSE 80 # Set the command to run when the container starts CMD ["dotnet", "MyApp.dll"]
Azure Container Instances
- Offers the fastest and simplest way to run a container in Azure without having to manage any VMs or adopt a higher-level service
- Benefits:
- Fast startup: Start containers in seconds without needing to provision and manage VMs
- Container access: Can expose container groups to the internet with an IP address and fully qualified domain name
- Hypervisor-level security: Isolate application as if it were in a VM
- Customer data: ACL stores the minimum data required to ensure container groups are running as expected
- Persistent storage: Mount Azure Files directly to a container to retrieve and persist state
- Linux and Windows: Schedule both Windows and Linux containers using the same API
- Container groups:
- The top-level resource in Azure Container Instances
- A collection of containers scheduled on the same host machine, they share a lifecycle, resources, local network and storage volumes
- Two common ways to deploy a multi-container group:
- Resource Manager template: Recommended for deploying more Azure service resources when you deploy the container instances
- YAML file: More concise in nature, recommended when your deployment includes only container instances
- ACIs allocate resources such as CPUs, memory and optionally GPUs to a container group by adding the resource requests of the instances in the group
- Container groups share an IP address and a port namespace on that IP
- The port must be exposed for external clients to reach a container within the group
- Containers within the group can reach each other via localhost ports that are exposed, even if they aren't exposed on the IP
- You can specify external volumes to mount within a container group
- Volumes can be mapped into specific paths within the containers
- Supported volumes include Azure file share, Secret, empty directories and cloned git repositories
- Scenarios:
- Useful in cases where you want to divide a single functional task into a few container images
- A container serving a web application and a container pulling the latest content from source control
- An application container and a logging container to collect logs and metrics
- An application container and a monitoring container to make requests and raise alerts
- A front-end container and a back-end container to serve a web application and running a service to retrieve data
Restart Policies
- Configure a restart policy to specify containers to stop when their processes are completed
- Since containers are billed by the second, you will only be charged for compute resources used while the task is executing
- There are three restart policy settings:
- Always: Containers in the group are always restarted, this is the default setting
- Never: Containers in the group are never restarted, containers run at most once
- OnFailure: Containers in the group are restarted only when the process executed in the container fails, containers run at least once
- Specify a restart policy:
az container create \ --resource-group myResourceGroup \ --name mycontainer \ --image mycontainerimage \ --restart-policy OnFailure
Environment Variables
-
Provide dynamic configuration of the application or script run by the container
-
Example with the CLI:
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'\
-
Objects with secure values are intended to hold sensitive information, recommended for passwords or keys
- Set a secure environment variable by specifying the secureValue property
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
az container create --resource-group myResourceGroup \ --file secure-env.yaml \
Mount an Azure File share in Azure Container Instances
- ACIs are stateless by default, if a container crashes / stops, it loses all its state
- A volume from an external store must be mounted to persist state beyond the container's lifetime
- Limitations:
- Can mount only Azure Files shares to Linux containers
- Azure File share volume mount requires the Linux container run as root
- Azure File share volume mounts are limited to CIFS support
- Example of deploying container and mount volume using CLI:
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/
- Example of deploying container and mount volume using YAML:
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
- Example mounting multiple volumes in a container instance:
"volumes": [{ "name": "myvolume1", "azureFile": { "shareName": "share1", "storageAccountName": "myStorageAccount", "storageAccountKey": "<storage-account-key>" } }, { "name": "myvolume2", "azureFile": { "shareName": "share2", "storageAccountName": "myStorageAccount", "storageAccountKey": "<storage-account-key>" } }]
"volumeMounts": [{ "name": "myvolume1", "mountPath": "/mnt/share1/" }, { "name": "myvolume2", "mountPath": "/mnt/share2/" }]
Containers in Azure Container Apps
- The service manages details of Kubernetes and container orchestration for you
- The following is an example configuration using ARM:
"containers": [ { "name": "main", "image": "[parameters('container_image')]", "env": [ { "name": "HTTP_PORT", "value": "80" }, { "name": "SECRET_VAL", "secretRef": "mysecret" } ], "resources": { "cpu": 0.5, "memory": "1Gi" }, "volumeMounts": [ { "mountPath": "/myfiles", "volumeName": "azure-files-volume" } ] "probes":[ { "type":"liveness", "httpGet":{ "path":"/health", "port":8080, "httpHeaders":[ { "name":"Custom-Header", "value":"liveness probe" }] }, "initialDelaySeconds":7, "periodSeconds":3 // file is truncated for brevity
- Can define multiple containers in a single container app to implement the sidecar pattern
- An example of a sidecar container can include agents for log reading and a background process that refreshes a cache
- Can deploy images hosted on private repositories by providing credentials in the Container Apps configuration
{ ... "registries": [{ "server": "docker.io", "username": "my-registry-user-name", "passwordSecretRef": "my-password-secret-name" }] }
- Limitations of Container Apps:
- Can't run on privileged containers
- Linux-based (linux/amd64) container images are required
Authentication and Authorisation in Azure Container Apps
- Provides built-in authentication and authorisation features to secure your external ingress-enabled container app with minimal or no code
- Ensure allowInsecure is disabled on container app's ingress configuration to only allow the feature on HTTPS
- Can use a federated identity, using identity providers such as Facebook, GitHub, Google, X, etc.
- Can add authorisation middleware which intercepts all incoming HTTP requests before your application
- Authentication flow depends on whether you sign in with an identity provider or manually through the provider SDK
Manage Revisions and Secrets in Azure Container Apps
- Revisions are immutable snapshots of a container app version
- Updating container app:
az containerapp update \ --name <APPLICATION_NAME> \ --resource-group <RESOURCE_GROUP_NAME> \ --image <IMAGE_NAME>
- List all revisions through this command
az containerapp revision list \ --name <APPLICATION_NAME> \ --resource-group <RESOURCE_GROUP_NAME> \ -o table
- Container Apps allow you to store sensitive configuration values
- Updated or deleted secrets aren't automatically reflected, must deploy a new revision or restart an existing revision
- Secrets are defined using --secrets parameter
az containerapp create \ --resource-group "my-resource-group" \ --name queuereader \ --environment "my-environment-name" \ --image demos/queuereader:v1 \ --secrets "queue-connection-string=$CONNECTION_STRING"
- The following example shows an application that declares a connection string at the application level. This connection is referenced in a container environment variable
az containerapp create \ --resource-group "my-resource-group" \ --name myQueueApp \ --environment "my-environment-name" \ --image demos/myQueueApp:v1 \ --secrets "queue-connection-string=$CONNECTIONSTRING" \ --env-vars "QueueName=myqueue" "ConnectionString=secretref:queue-connection-string"
Dapr Integration with Azure Container Apps
- Distributed Application Runtime (DAPR) is a set of incrementally adoptable features
- Uses a modular design where functionality is delivered as a component
- Dapr components in container apps are environment-level resources that:
- Provide a pluggable abstraction model for connecting to supporting external services
- Shared across container apps or scoped to specific container apps
- Use Dapr secrets to securely retrieve configuration metadata