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,
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,
- steps:
- - task: Docker@0
- displayName: 'Build an image'
- inputs:
- azureSubscription: 'Azure'
- azureContainerRegistry: '{"loginServer":"containersacr.azurecr.io", "id" : "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/ResourceGroup/providers/Microsoft.ContainerRegistry/registries/containersacr"}'
- dockerFile: DockerSample/DockerSample/Dockerfile
Push the Image to Azure Container Registry using Azure DevOps Pipeline CI,
- steps:
- - task: Docker@0
- displayName: 'Push an image'
- inputs:
- azureSubscription: 'Azure'
- azureContainerRegistry: '{"loginServer":"containersacr.azurecr.io", "id" : "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/ResourceGroup/providers/Microsoft.ContainerRegistry/registries/containersacr"}
- 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.
- az acr import \
- --name myregistry \
- --source aci-helloworld:latest \
- --image aci-helloworld:latest \
- --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,
- steps:
- - task: AzureCLI@2
- displayName: 'Azure CLI '
- inputs:
- azureSubscription: 'Azure'
- scriptType: batch
- scriptLocation: inlineScript
- inlineScript: |
- az acr import \
- --name myregistry\
- --source aci-helloworld:latest \
- --image aci-helloworld:latest \
- --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.
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.