Graduate Program KB

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

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