build-docker-devops-ci

Build CI Pipeline for Docker in  Azure DevOps

In this post I want to build  microservices in an other Azure DevOps CI pipeline and push the images to Docker Hub

Setting up a Service Connection to Docker Hub

In Azure Devops  I select your project (in my case ProductMicroservice-DotNET-Core-Master)  to create new CI Pipeline for building the Docker image, and set up a connection to Docker Hub to push the image to its repository. To do that in Azure DevOps, click on Project Settings –> Service connections –> New service connection. as following image:

Create Service connection for Docker
Create Service connection for Docker

Press to new Service connection  and then search Docker in the Search list of Services as following:

Select Docker Registry for your service connection
Select Docker Registry for your service connection and press Next button

in the new window (see following) select Docker Hub and write your Docker ID and Docker password that you have registered, and then press to Verify then you se Verification Succeeded.

Service connection configuration

Checkmark the checkbox: Grant access permission to all pipelines and press to Verify and save button then you have the following image:

Service connection is registered

 Creating  new Azure DevOps CI Pipeline

To create a new CI Pipeline. Select the source code location and then any template (for me: ProductMicroservice-DotNET-Core-Master). After the yml file is created, delete its content. To see more details on creating a Pipeline, see my post “Microservice-dotnet-core-ci-pipeline-azure-devops”.

you can first create  .yml file  first in the Github and name it Product-docker-CI.yml and after that create CI-Pipeline.

Now we have an empty file: Product-docker-CI.yml

Configure the Pipeline

Set up some basic configuration for the pipeline, give it a name, set a trigger to run the pipeline every time a commit is made to master and use an Ubuntu agent. Additionally, the build should only be triggered if changes to the ProductMicroservice folder are made. You can do this with the following code:

name : ProductMicroservice-CI
trigger:
  branches:
    include:
      - master
  paths:
    include:
      -  ProductMicroservice/*
pool:
  vmImage: 'windows-latest'

Next step, up the variables for pipeline.  I define a name and set the tag to the build id using the built-in variable $(Build.BuildId). This increases the tag of  image automatically every time when a build runs.

variables:
  ImageName: 'mehzan07/ProductMicroservice:$(Build.BuildId)'

Build the Docker Image

Now that everything is set up, let’s add a task to build the image. Before you can do that, you have to add a stage and a job. You can use whatever name you want for your stage and job. For now, you only need one. It is good practice to use a meaningful name though.

Inside the job, add a task for Docker. Inside this task add your previously created, service connection (Docker Hub), path to the dockerfile, an image name, and the build context. As the command use Build an Image.

stages:
- stage: Build
  displayName: Build image
  jobs:
  - job: Build
    displayName: Build and push Docker image
    steps:
    - task: Docker@1
      inputs:
        containerregistrytype: 'Container Registry'
        dockerRegistryEndpoint: 'Docker Hub'
        command: 'Build an image'
        dockerFile: '**/Dockerfile'
        imageName: '$(ImageName)'
        useDefaultContext: false
        buildContext: 'ProductMicroservice'
      displayName: 'Build the Docker image'

Pushing  Image to Docker Hub

In the last step is pushing image to a registry. I am using Docker Hub because it is publicly available but you can also use a private one like Azure Container Registry (ACR) or even a private Docker Hub repository.

Add the following code to your pipeline:

- task: Docker@1
  inputs:
    containerregistrytype: 'Container Registry'
    dockerRegistryEndpoint: 'Docker Hub'
    command: 'Push an image'
    imageName: '$(ImageName)'
  condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
  displayName: 'Push the Docker image to Dockerhub'

I set  container registry “Container Registry” dockerRegistryEndpoint: “Docker Hub” which is the previously created service connection. The command indicates that we want to push an image and I have set the image name from the previously created variable (‘$(ImageName)).  The condition says that the task only runs when the task was successful and  the build is not triggered by a pull request.

The finished Azure DevOps CI Pipeline is as following:

name : ProductMicroservice-CI
trigger:
  branches:
    include:
      - master
  paths:
    include:
      - ProductMicroservice/*
pool:
  vmImage: 'ubuntu-latest'
variables:
  ImageName: 'mehzan07/ProductMicroservice:$(Build.BuildId)'
stages:
- stage: Build
  displayName: Build image
  jobs:
  - job: Build
    displayName: Build and push Docker image
    steps:
    - task: Docker@1
      inputs:
        containerregistrytype: 'Container Registry'
        dockerRegistryEndpoint: 'Docker Hub'
        command: 'Build an image'
        dockerFile: '**/Dockerfile'
        imageName: '$(ImageName)'
        useDefaultContext: false
        buildContext: 'ProductMicroservice'
      displayName: 'Build the Docker image'
    - task: Docker@1
      inputs:
        containerregistrytype: 'Container Registry'
        dockerRegistryEndpoint: 'Docker Hub'
        command: 'Push an image'
        imageName: '$(ImageName)'
      condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
      displayName: 'Push the Docker image to Dockerhub'

Testing the Azure DevOps CI Pipeline

with tesng of Pipeline I have got some errors which was depended on the Dockerfile which was generated by Visual studio, One of Error was:

 receiving the missing MAIN method error, not having a suitable static main entry point,

I have fixed this by replacing##COPY . .  to COPY . ProductMicroservice/ in Dockerfile

I have done some modification in Docker file and the results is shown as following and the original lines are commented. original lines are red and new lines are green.

The code of Dockerfil can be found here

Run the Pipeline by pressing to Save and Run button.

Then we see that build has been succeded as followoing image:

Docker pipeline ran successfully

And if we check the Doker Hub we see that the image has been published in the as following:

Docker image has been pushed to Docker Hub

the yml file is in ProductMicroservice-DotNET-Core-Master/Pipelines/Product-docker-ci.yml

The code can  found on my GitHub.

Conclusion

By this post  I have showed that an automated  docker CI pipeline to build and push new images is an integral point of every DevOps process. It  is  easy to automate everything and create a new image every time changes are pushed to the master branch.

In my next post, I will explain  how to create a REST API, connect to SQL local DB , create a CI Pipeline  in Azure DevOps, deploy the SQL local DB to Azure SQL, create API App in Azure Cloud and deploy Rest API to  to Azure API App by using Azure DevOps Pipeline Release (CI/CD process).

This post is part of Azure DevOps step by step.

Back to home page

 

Leave a Reply

Your email address will not be published. Required fields are marked *