Promoting Container Images To Production Using Azure DevOps

Containers make our lives simple with "Build Once Deploy Anywhere".
 
It's to build images and run them on local or dev-test environments, but let's see how to take them on the full cycle of creating the images, promoting them as an artifact from dev to production using Azure DevOps. 
 

Challenges

  •  How to carry the artifact (container image) across environments without rebuilding the image again for each environment.
  •  Not all the dev images qualify for production so we cannot push the image to all the environment registries on the development stage.
  •  Rollback operations on any production release failures.
Here is one of the best practices.
 
I will be following for promoting the images from dev to higher environment by using environment-specific container registries,
Promoting Container Images to Production using Azure DevOps
source: https://cdn-images-1.medium.com/max/800/1*8bzqBzT4E0ZvqYbXriqvDQ.png
 

How can we achieve this by using Azure DevOps Pipelines and Azure Container Registry?


Let us build an image first using the Azure DevOps Pipeline.
 
Build an Image using Azure DevOps Pipeline CI,
  1. steps:    
  2. - task: Docker@0    
  3. displayName: 'Build an image'    
  4. inputs:    
  5. azureSubscription: 'Azure'    
  6. azureContainerRegistry: '{"loginServer":"containersacr.azurecr.io", "id" : "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/ResourceGroup/providers/Microsoft.ContainerRegistry/registries/containersacr"}'    
  7. dockerFile: DockerSample/DockerSample/Dockerfile    
Push the Image to Azure Container Registry using Azure DevOps Pipeline CI,
  1. steps:    
  2. - task: Docker@0    
  3. displayName: 'Push an image'    
  4. inputs:    
  5. azureSubscription: 'Azure'    
  6. azureContainerRegistry: '{"loginServer":"containersacr.azurecr.io""id" : "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/ResourceGroup/providers/Microsoft.ContainerRegistry/registries/containersacr"}    
  7. action: 'Push an image'    
Prerequisite
 
Service connection to your Azure Container Registry and Azure Subscription is required
 

Promote an Image to different environment ACR’s

 
Using Azure CLI we can perform this move here is the inline script, you can use a script file also.
  1. az acr import \    
  2. --name myregistry \    
  3. --source aci-helloworld:latest \    
  4. --image aci-helloworld:latest \    
  5. --registry /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/sourceResourceGroup/providers/Microsoft.ContainerRegistry/registries/mysourceregistry    
Note
On the above-mentioned sample, the source and destination subscription are under the same Azure Tenant.
 
More samples about working with external registries and multiple tenant azure subscriptions are available here.
 

Promote the Image from one registry to another using Azure DevOps Release Pipeline

 
This step on Azure DevOps Release Pipeline would move your image from the source registry to the destination registry.
 
Here is the full step YAML, 
  1. steps:    
  2. - task: AzureCLI@2    
  3. displayName: 'Azure CLI '    
  4. inputs:     
  5.  azureSubscription: 'Azure'     
  6.  scriptType: batch    
  7.  scriptLocation: inlineScript    
  8.  inlineScript: |    
  9.    az acr import \    
  10.    --name myregistry\    
  11.    --source aci-helloworld:latest \     
  12.    --image aci-helloworld:latest \    
  13.    --registry /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/sourceResourceGroup/providers/Microsoft.ContainerRegistry/registries/mysourceregistry    
Note
Service Connection(Azure Subscription) used here should be of the destination registry.
 
Promoting Container Images to Production using Azure DevOps
https://cdn-images-1.medium.com/max/800/1*I4UY_SG0cIhii25r_MSj7w.png
 
Once the Promote Image step is added the next steps are of deployments of your choice, I have chosen the app service for container deployment.
 

What happened to the Challenges?

 
These steps mentioned above would solve the challenges mentioned to a greater extend,
  • Build Image once using the CI
  • Promote only the qualified images to higher environments
  • Rollback to the last build image instantly with the previous release in Azure DevOps
Furthermore on App Service for Container supports Slot swapping which ensures draining of connections before swapping, this can be achieved by simply deploying to the production  slot rather than the production  app service itself.