A modern application isn’t complete without a proper CI/CD process in place. CI/CD involves taking code from a code repository, automatically building artifacts, and testing against it to ensure the software is ready to deliver to another environment. In this lesson, we’ll learn to work with Docker in various CI environments.

Working with Docker in CI is no different than working in a local environment. Most commands that we use on our local machine will be applicable in the CI environment. In the local environment, we write code, build, run, and test. Similarly, in the CI environment, we build our code, run tests, push artifacts to the code artifacts repository, and deploy.


GitHub Actions is GitHub’s owned CI/CD and is well-integrated with GitHub.

GitHub Actions allows us to create workflows that can be used to build or compile, test, and deploy our code within our repository.

GitHub Actions is based on some key concepts that are important for us to know so that we can understand how everything ties together.


In GitHub Actions, everything starts with an event. An event is an action or activity that triggers a workflow. It could be a commit action, a pull request action, a merge action, a comment action, and so on.


An event triggers something called a workflow. We can think of workflow as automated instructions that we have configured. It’s a combination of one or more jobs. A workflow to build a Docker image for an application could begin from building the application, running unit tests, running end-to-end tests, tagging, and pushing the image to a Docker registry.


A job is any task we want to do. It may contain one or more steps that run on the same runners.


A step is a task that can run commands in a job. Suppose we have a job to read a book. The steps to reading that book could be as follows:

  1. Search for the book.
  2. Buy the book.
  3. Receive the book delivery.
  4. Open the book.
  5. Read the book.

In GitHub Actions, a step can be either an action or a shell command.


Actions are standalone commands combined into steps to create a job. We can create our own action, or we can use actions created by the community.


We can think of a runner as a server with GitHub Actions installed that runs our jobs. It listens for jobs available, runs one at a time, reports the progress, and logs and sends results back to GitHub.

Everything is beautifully tied up together in the following way. An event automatically triggers a workflow, which contains a job. The job then uses steps to control the order in which actions are run. The actions are installed in the runners (servers) to help us execute the jobs.

On a high level, a GitHub action looks like this:

name: greet-github-action
on: [push]
    runs-on: ubuntu-latest
      - run: echo 'Hello world!'
  • name: This is the name of our action.
  • on: This specifies the action that should trigger the workflow.
  • jobs: These are the things we want to perform or do.

GitHub actions reside in the .github/workflows directory, and we can create as many actions as possible.

- .github
  |- workflows
    |- action1.yml
    |- action2.yml

Work with Docker in GitHub Actions

This repository contains an example application we’ll use for this lesson.

We can clone the repository by running this:

git clone ​​https://github.com/abiodunjames/docker-lessons-sample-app.git

Define CI requirements#

First, the CI workflow must meet the following requirements:

  • The CI should be triggered only when a commit is pushed to the master branch or when a pull request is merged to the master branch.
  • The CI should build a Docker image of the application.
  • Automated tests should run to ensure that new changes don’t break existing features. If a test fails, the build should fail.
  • Finally, if previous steps succeed, the built Docker image should be pushed to a Docker registry.

Take care of external dependencies

There are two external dependencies from the requirements above:

  • Docker image repository: To push the Docker image to a registry, we need to create an image repository for the image.

  • CI access credentials: For the CI to be able to push an image to a repository, it needs to be authenticated with valid credentials.

Create a Docker image repository

To create an image repository, we follow the steps below:

  1. Log in to Docker Hub.
  2. Click on “Repositories” at the top navigation menu.
  3. Click on the “Create Repository” button at the right corner.
  4. Create a repository for the application and note down the repository name.

Generate the Docker Hub access token

To generate an access token that’ll be used by the CI to authenticate to Docker Hub, we follow the steps below:

  1. Click on our username in the top right corner and select “Account Settings.”
  2. Select “Security” and then “New Access Token.”
  3. Add a description for the token and create a new token.
  4. Note down the token and username generated.

Import Docker Hub access credentials as GitHub secrets

Once the access credentials are generated, we need to make them available to GitHub Actions. We can do that by creating them as secrets on GitHub. We can do so through the following steps:

  1. On GitHub, go to the code repository.
  2. Under the repository name, click on “Settings.”
  3. In the left sidebar, click on “Secrets.”
  4. Click on the “New Repository Secret” button.
  5. Type DOCKER_USERNAME as the secret’s name and our Docker Hub username as the value.
  6. Create the second secret.
  7. Type DOCKER_TOKEN as the secret’s name and the Docker access token created earlier as the value.

Create a free account to view this lesson.

By signing up, you agree to Educative's Terms of Service and Privacy Policy