Docker Workflow

Hello everyone!

I am new to GitHub Actions. I am wondering if there are experienced people who can offer advice on setting up CI pipeline involving Docker container.

Ideally, I would like to do the following inside the same job: (1) build the Docker image, (2) run unit tests inside the container, (3) push the built image up to Docker Hub if the tests pass.

That’s definitely possible, I have an example of a similar setup here (pushing to GHCR instead): https://github.com/airtower-luna/hello-ghcr/blob/763f10f3fdc33e8bcef1d04508a3264cf1a06c16/.github/workflows/build.yaml

I just use the regular docker commands in the steps. Note that the docker logout at the end is run with if: always() to make sure the credentials are removed even if any intermediate step fails. There are also some pre-made actions like docker/login-action available if you prefer.

Your tests will probably look pretty different, for the simple test container I only do docker run and check if the output looks as expected. :wink:

1 Like

Thanks very much for this.

I don’t know much about writing logic inside of YAML files, do you have any suggested resources?

Specifically, I want to write logic where I have this step

- name: Build Docker Image
   run: docker build -t image_name:TAG_NAME .

where TAG_NAME is ‘staging’ if I push to develop branch and ‘prod’ if I push to master branch

1 Like

There isn’t much. YAML itself is structured data. Github Actions defines some fields that can contain logic (mostly if: on steps or jobs). Most of the logic in your workflow will have to be in the steps.

You might have noticed this step in my example:

      - name: Generate container tag(s) and name
        run: |
          TAGS=$(python3 tag-from-ref.py ${{ github.ref }})
          echo "::set-env name=TAGS::${TAGS}"
          echo "::set-env name=CONTAINER_NAME::${{ github.repository_owner }}/hello-ghcr-meow"

The tag-from-ref.py processes ${{ github.ref }} to decide which tag(s) to use, and the result is then stored in an environment variable.

Whether it makes sense to create a script file like I did or put the script directly into a step is part a matter of taste and also depends on how complex your selection is. You could just do something like this for what you described:

      - name: Generate container tag
        run: |
          if [ "${{ github.ref }}" = "refs/heads/develop" ]; then
              echo "::set-env name=TAG_NAME::staging"
          elif [ "${{ github.ref }}" = "refs/heads/master" ]; then
              echo "::set-env name=TAG_NAME::prod"
          else
              # whatever you want to do for other branches/tags
          fi
1 Like

Thanks for your help.

I have adapted the logic you have written and workflow is working as intended.

I have also learned quite a bit about the general process, previously I was very unfamiliar.

1 Like