How to Build and Deploy Docker Images from Azure DevOps to AWS ECR

This guide describes how to build a docker image and publish the docker image to AWS Elastic Container Registry (AWS ECR). ECR is a service to host private Docker images in AWS.

Prerequisite

  • This guides assumes that there is a Dockerfile in the root folder of the project
  • An AWS account
  • An AWS user with programmatic access. Remember to note down the access key and the secret for the user
  • An Azure DevOps project

Step 1: Create an AWS ECS Repository

Go to the ECR service in AWS and create a new repository. Remember to note the repository url. The repository url will consist of your account number, region, AWS ECR service url and your repository name. E.g: AWS_ACCOUNT_ID.dkr.ecr.AWS_REGION.amazonaws.com/DOCKER_REPOSITORY_NAME.

Step 2: Create the Azure DevOps Pipeline Build File

By storing the Azure DevOps Pipeline configuration one can have versions control of the build pipeline. That makes it a lot easier to spot errors and changes to the build pipeline. Create a new file called build-pipline.yml. In the steps below the contents of the build file are explained.

Trigger

Triggers are used to tell Azure DevOps when the build pipeline should run. The snippet below defines that the pipeline should run each time the master branch gets new changes.

trigger:
  branches:
    include:
    - master

Build image

The following lines tells the pipeline to pick the latest available Ubuntu image as the VM image.

pool:
  vmImage: 'ubuntu-latest'

Variables

Variables should not be stored in the build file. This can be avoided by storing the variables and secrets in a library, which can be found at Piplines -> Library. The following variables are needed for this guide to work:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY_ID
  • AWS_REGION
  • AWS_ACCOUNT_ID
  • DOCKER_REPOSITORY_NAME

The variables are made available by adding the group name. In this example the group is called dev. Additionally one inline variable named DOCKER_REPOSITORY is defined, which stores the docker repository url.

variables:
  - group: dev
  - name: DOCKER_REPOSITORY
    value: $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_REGION).amazonaws.com/$(DOCKER_REPOSITORY_NAME)

Docker Login

The Docker registry requires authentication before any images can be pushed. Authentication can be done using a bash script. The AWS CLI is available by default. It is not possible login directly into AWS ECR using the Docker CLI. Authentication is done using a one time password obtained running the AWS ECR CLI command get-login-password. The ECR command uses the API keys to authenticate. After obtaining the one time password, the password is piped into the Docker CLI command. Logging in to the registry can then be done with a user named AWS and with the one time password piped from the previous step. The option --password-stdin is needed for the command to pickup the password. The Docker registry url is added at the end of the login command.

steps:
- script: |
    aws ecr get-login-password --region $(AWS_REGION) | docker login --username AWS --password-stdin $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_REGION).amazonaws.com
  displayName: 'Login to AWS'
  env:
    AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID)
    AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)

Docker Build and Push

Azure DevOps has a built in task for Docker which can be used to build and push the image in one task. The Docker task requires a few inputs to work:

  • repository - the repository url for the image
  • command - buildAndPush is the combined command to use to build and push in one task
  • Dockerfile - add the location of the Dockerfile
  • tags - an array of the tags
- task: Docker@2
  displayName: Build docker image
  inputs:
    repository: $(DOCKER_REPOSITORY)
    command: buildAndPush
    Dockerfile: Dockerfile
    tags: |
      latest

Complete file

trigger:
  branches:
    include:
    - master

pool:
  vmImage: 'ubuntu-latest'

variables:
  - group: dev
  - name: DOCKER_REPOSITORY
    value: $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_REGION).amazonaws.com/$(DOCKER_REPOSITORY_NAME)

steps:
- script: |
    aws ecr get-login-password --region $(AWS_REGION) | docker login --username AWS --password-stdin $(AWS_ACCOUNT_ID).dkr.ecr.$(AWS_REGION).amazonaws.com
  displayName: 'Login to AWS'
  env:
    AWS_ACCESS_KEY_ID: $(AWS_ACCESS_KEY_ID)
    AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)

- task: Docker@2
  displayName: Build docker image
  inputs:
    repository: $(DOCKER_REPOSITORY)
    command: buildAndPush
    Dockerfile: Dockerfile
    tags: |
      latest

Step 3: Create a Pipline in Azure DevOps

Go to the Piplines tab in Azure DevOps and create a new pipeline. If the code is hosted in Azure DevOps select Azure Repos Git and select the git repository in the next step. Under the Confgure your pipeline step, select the option Existing Azure Pipelines YAML file. Then choose the git branch and the location of the pipeline config file created in the beginning of this guide. In the Review step click save to publish the pipeline.

You are now all setup! The pipeline should build and deploy your Docker image each time you push new code to the master branch in your git repository.

If you want to support this blog you can do so by signing up to DigitalOcean using this referral link.