Introduction
This is the second article in the series and here, we are going to set up a Microsoft Azure DevOps build pipeline to automate the tasks. We did that manually in the first article of the series. Each time we push a change to the master branch, the build will be triggered to build our application, then build a Docker image, and push it to the Docker Hub.
If you have been following along, you must have -
- a GitHub repository
- a working web application in ASP .Net Core (or something similar)
- a Docker Image for the application
- a running container to host your application locally
There are tree parts in this series,
- Develop an ASP .Net Core web application and containerize it with Docker
- Setup Continuous Integration with Microsoft Azure DevOps Pipeline and GitHub - This one
- Setup a Continuous Deployment pipeline to deploy the application as a Docker container on Azure Web App Service
Docker Registry
First, you need to set up an account at Docker Hub. After that, create a repository where you can keep Docker images for your application.
You already have a Docker image built in the previous steps, that works well. So now, you can tag that image with the repository name. However, the Docker client running on your local machine needs to connect with the Docker Hub account, before you can push the image.
The following commands tag the local image for Docker Hub repository, authorize the Docker client and finally push the image to Docker Hub.
- $ docker tag <image-name> <namespace>/<repository>:<tag>
- // example
- $ docker tag webapp quickdevnotes/webapp:v1
- // login to your Docker Hub account
- $ docker login
- username: quickdevnotes
- password:
- // push the to Docker Hub
- $ docker push quickdevnotes/webapp:v1
Note that I'm using a public repository at Docker Hub. If you are using a private repository, then you will have to first login using the docker login command and then push the image. Otherwise, the push will fail with authorization error.
Azure DevOps - Project
Now comes the interesting part. To start using the Azure DevOps pipelines, you first need to have a user account. If you already have an account, great, you are good to start or you can register here.
Once you are in, it asks you to create an organization and where you want to host your project. Name it anything you like and select a region suitable to your need:

Next, we have to create a project under the organization. Select +Create Project from the top right, and provide the required details.
From the "Advanced" section we don't need anything for this series. So, I leave the choice up to you.
Continuous Integration (Build Pipeline)
It's finally time to automate the manual steps. From Pipelines > Builds select New Pipeline.
Where is your code?
The first thing Azure pipeline needs is to connect with your application code repository. So, on the Connect tab, select GitHub a connection to your GitHub.

After that, you will be prompted with OAuth authentication to authorize Azure Pipelines for accessing the GitHub repository. Grant the authorization and provide credentials as required.

Select a repository
Once the authorization completes, you can see a list of repositories from the GitHub account. From the list of repositories select your application repository, which then prompts you to Install Azure Pipelines. Use the "only select repositories" option and from the drop-down select your application repository.

If you want to install Azure Pipelines for all current and future repositories select "All repositories" and click install.

azure-pipelines.yaml
The Azure pipeline is smart enough to analyze your application repository and provide a basic azure-pipelines.yml file. This YAML file lies at the root of your GitHub repository and is used by the Azure build pipeline to perform certain tasks like building the application, executing tests, building Docker Image and many more.
Here is the azure-pipelines.yml file for my build pipeline. I know, it can be overwhelming; but everything will be clear after we talk about each task in detail.
- trigger:
- - master
- pool:
- vmImage: 'Ubuntu-16.04'
- variables:
- imageName: 'quickdevnotes/webapp:$(build.buildNumber)'
- steps:
- - script: dotnet test WebApp.Tests/WebApp.Tests.csproj --logger trx
- displayName: Run unit tests
- - task: PublishTestResults@2
- condition: succeededOrFailed()
- inputs:
- testRunner: VSTest
- testResultsFiles: '**/*.trx'
- - task: Docker@1
- displayName: Build an image
- inputs:
- command: Build an image
- containerregistrytype: Container Registry
- dockerRegistryEndpoint: DockerHub
- dockerFile: Dockerfile
- imageName: $(imageName)
- imageNamesPath:
- restartPolicy: always
- - task: Docker@1
- displayName: Push an image
- inputs:
- command: Push an image
- containerregistrytype: Container Registry
- dockerRegistryEndpoint: DockerHub
- dockerFile: Dockerfile
- imageName: $(imageName)
- imageNamesPath:
- restartPolicy: always






Join the conversation! Your thoughts help the community grow.