Docker Container Building via GitHub Actions

So if you’ve been to my site before, you might remember that I setup a locally hosted Jenkins instance for building Docker containers. However I have since decided to retire the VM hosting that instance and it was getting tedious to keep on-top of the Jenkins updates. So I moved my docker container building to GitHub actions.

Shows GitHub actions tab.

The image above shows the Actions tab view of my private repo on GitHub. At the moment I have my alexandzors/caddy:v2 image building successfully, albeit not fully automatic yet. My other containers though are still being migrated and are having issues at the moment. So for this post we will be focusing on getting V2 of Caddy building as a docker container in GitHub Actions.

Setting things up.

First I had to setup the directory in which the workflows were going to be housed in the repo.

/gitrepo/.github/workflows

We then need to make the configuration file for the workflow.

/gitrepo/.github/workflows/caddy.yml

Since I am pushing these images to Docker Hub, I had to also create two secrets for my repo for my login credentials. These are located in Repo > Settings > Secrets. I actually used a PAT (Personal Access Token) instead of my regular password.

Shows repo settings/secrets view

Creating the workflow.

So once everything is setup and ready we can create the workflow configuration.

name: alexandzors/CaddyV2
on:
  push:
    branch:
      - containers
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/[email protected]
    - name: docker login
      run: |
        echo ${{ secrets.DOCKER_HUB_PW }} | docker login -u ${{ secrets.DOCKER_HUB_USR }} --password-stdin
    - name: docker build CaddyV2
      if: success()
      run: |
        docker build -f ./Build_Scripts/Docker/CaddyV2/Dockerfile -t alexandzors/caddy:v2 .
    - name: docker push
      if: success()
      run: |
        docker push alexandzors/caddy:v2

Above is the completed workflow for building the :v2 tag of my caddy image. The file can be easily explained as its just a simple workflow.

The first section defines the name of the workflow [alexandzors/CaddyV2] as well as when to build it.

name: alexandzors/CaddyV2
on:
  push:
    branch:
      - containers

For my mine I have it build automatically when the containers branch is pushed. The second part defines the actual job to run. This can be broken down into a few smaller portions.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/[email protected]
    - name: docker login
      run: |
        echo ${{ secrets.DOCKER_HUB_PW }} | docker login -u ${{ secrets.DOCKER_HUB_USR }} --password-stdin
    - name: docker build CaddyV2
      if: success()
      run: |
        docker build -f ./Build_Scripts/Docker/CaddyV2/Dockerfile -t alexandzors/caddy:v2 .
    - name: docker push
      if: success()
      run: |
        docker push alexandzors/caddy:v2

The first portion of the second section defines the build environment. Which for this image I am using the ubuntu-latest environment as it includes docker. It also tells the job to checkout the repo.

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/[email protected]

The next section defines what the actual job is.

    - name: docker login
      run: |
        echo ${{ secrets.DOCKER_HUB_PW }} | docker login -u ${{ secrets.DOCKER_HUB_USR }} --password-stdin
    - name: docker build CaddyV2
      if: success()
      run: |
        docker build -f ./Build_Scripts/Docker/CaddyV2/Dockerfile -t alexandzors/caddy:v2 .
    - name: docker push
      if: success()
      run: |
        docker push alexandzors/caddy:v2

Here you can see that I have a few steps (marked with hypens ‘-‘). The first step runs the docker login command so that I am able to push to Docker Hub. This is using Environment variables which corollate to my secrets I setup earlier.

  • ${{ secrets.DOCKER_HUB_PW }} = Docker Hub PAT
  • ${{ secrets.DOCKER_HUB_USR }} = Docker Hub Username

Now this command uses the password-stdin option with echo so that the PAT isn’t stored in any runtime logs or shell history.

    - name: docker login
      run: |
        echo ${{ secrets.DOCKER_HUB_PW }} | docker login -u ${{ secrets.DOCKER_HUB_USR }} --password-stdin

The next step checks to make sure if the previous step was successful and if it is it then builds the container via the defined Dockerfile located in my Build_Scripts directory.

    - name: docker build CaddyV2
      if: success()
      run: |
        docker build -f ./Build_Scripts/Docker/CaddyV2/Dockerfile -t alexandzors/caddy:v2 .

The final step in the workflow pushes the container to Docker Hub. Then the workflow automatically cleans itself up (GitHub Actions does this automatically).

    - name: docker push
      if: success()
      run: |
        docker push alexandzors/caddy:v2

Wrapping Up.

At first I wasn’t sure how well GitHub Actions was going to work for this. I found out that you can actually do a lot with them. So if you are like me and have a GitHub repo + a local Jenkins install for building. Consider switching to GitHub Actions to build your containers as it can lessen the load you have on your local env.

Docker Hub view of my caddy image with the V2 tag.

Alexandzors/Caddy on Docker Hub

Tags: latest, stats, v2

Leave a Reply