Click here to Skip to main content
15,041,403 members
Articles / DevOps / Continuous Integration
Article
Posted 31 Mar 2021

Stats

2.1K views

How to Create a Continuous Integration Continuous Deployment (CI-CD) Solution for a Docker Project

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
31 Mar 2021CPOL3 min read
How to build a continuous integration and continuous deployment solution for Docker
This post is about how I build a continuous integration and continuous deployment solution for my Docker project.

I'm not a Docker master, but I understand that it's very useful and I like to use it from time to time in some projects. Another thing I like is DevOps and automation and in a project I have, I was missing that. In the previous setup, the container was built and published to DockerHub with the date as a tag. Nice but not very easy to know which versions are "stable" and which one is "in progress".

This post is about how I build a continuous integration and continuous deployment solution for my Docker project. All the code is on GitHub and Docker Hub. I am sharing my journey so others can enjoy that automation and not spend a weekend building it.

Image 1

The Goal

By the end of this build, there will be two GitHub Actions to build and publish a different version of the application on Docker Hub.

The release version: Every time a release is published on GitHub, a container tag with the matching version number will be built and published. (example: myapp:v1)

The beta version: At every push in my branch on GitHub, a container will be published with a specific tag. The tag will be matching the draft release version number with -beta. (example: myapp:v2-beta).

In this post, the application is a Node.js Twitch chatbot. The type of application is not important - the post focuses on the delivery.

Publishing the Release Version

Every time a release is published on GitHub, the workflow will be triggered. It will first retrieve the "release version", then build and tag the container with it and finally publish (aka push) it to Docker hub. Because a "release" is also a "stable" version, it will also update the container tag latest.

Let's look at the full YAML definition of the GitHub Action and I will break it down after.

yaml
name: Release Docker Image CI

on:
  release:
    types: [published]
jobs:
  update:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Set outputs
      id: vars
      run: echo ::set-output name=RELEASE_VERSION::$(echo ${GITHUB_REF:10})
    - name: Publish to Registry
      uses: elgohr/Publish-Docker-Github-Action@master
      with:
        name: ${{secrets.DOCKER_USER}}/cloudbot
        username: ${{ secrets.DOCKER_USER }}
        password: ${{ secrets.DOCKER_PASSWORD }}
        tags: "latest,${{ steps.vars.outputs.RELEASE_VERSION }}"

To limit how many times the workflow is triggered, I used on: release and the type: published, adjust as you like.

The next interesting part is the lines in the step vars.

yaml
- name: Set outputs
    id: vars
    run: echo ::set-output name=RELEASE_VERSION::$(echo ${GITHUB_REF:10})

Here, I use the environment variable GITHUB_REF (striped of the 10 first characters contains "refs/tags/") to initialize a local variable RELEASE_VERSION. The value is available from the outputs of that step, like on the last line of the YAML.

yaml
tags: "latest,${{ steps.vars.outputs.RELEASE_VERSION }}"

From the steps identified by the id vars, I retrieved from the outputs the value of RELEASE_VERSION.

In this GitHub Action, I used elgohr/Publish-Docker-Github-Action@master because it was simple and was doing what I need. You can execute docker commands directly if you prefer or use the docker/github-actions.

There are many options available from the GitHub marketplace.

Publishing the Beta Version

Every time a push is done on GitHub, the workflow will be triggered. It will first retrieve the "release version" of the most recent release in draft mode. The workflow will happen -beta to the retrieved version and use this to tag the container. Finally, publish (aka push) it to Docker hub.

Once more, here full YAML, I will break it down after.

yaml
name: Build Docker Images
on: [push]
jobs:
  build:
    name: cloudbot-beta
    runs-on: ubuntu-latest
    steps:
    - id: last_release
      uses: InsonusK/get-latest-release@v1.0.1
      with:
          myToken: ${{ github.token }}
          exclude_types: "release, prerelease"
          view_top: 1  
    - uses: actions/checkout@v2
    - name: Publish to Registry
      uses: elgohr/Publish-Docker-Github-Action@master
      with:
        name: ${{secrets.DOCKER_USER}}/cloudbot
        username: ${{ secrets.DOCKER_USER }}
        password: ${{ secrets.DOCKER_PASSWORD }}
        tags: "${{ steps.last_release.outputs.tag_name }}-beta"

Here, the difficulty was that I wanted to create a tag from a "future" version. I decided to use the Draft Releases because those are not visible by everyone, therefore they look like the future.

If your last release is version 1 (v1.0), to make this workflow possible, you will need to create a new release and save it in Draft.

Image 2

Like in the Release workflow, I need to retrieve the version. Because drafts are only visible to some people, we will need to get access. This is easily done by using a github.token. Those are created automatically when the GitHub Action starts.

Then using the step InsonusK/get-latest-release, we will retrieve the version.

yaml
- id: last_release
    uses: InsonusK/get-latest-release@v1.0.1
    with:
        myToken: ${{ github.token }}
        exclude_types: "release, prerelease"
        view_top: 1

This time when passing the value for the tag, we will concatenate "-beta" to it.

yaml
tags: "${{ steps.last_release.outputs.tag_name }}-beta"

Image 3

Wrapping Up

And voila, a very simple and easy to implement ci-cd for a container project. There are many different options, looking forward to learning how you did yours?

History

  • 31st March, 2021: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Frank Boucher
Canada Canada
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --