Motivation
I have a multi-docker [repo] that stores a few containers for different tasks/projects. I want to be able to push an updated container to the [github container registry (ghcr.io)] every time I have a new commit to the repository.
Requirements:
- Docker images are organized in sub-folders [repo]
- Docker-build is run with a single github action definition yaml file (as opposed to [one yaml per image])
- Not recreating all containers if I am only making changes changes to only one image
Github action yaml file
TLDR; the action yaml is at [here]
Setup workflow
For github actions, we need to define when the action is run. For this wokflow, I want to trigger it for all pull requests and pushes.
And we can also setup some environment variables as well to define the container registry and image name.
name: Push and publish to Docker Hub
on: [push, pull_request]
env:
REGISTRY: ghcr.io
IMAGE_NAME_BASE: ${{ github.repository }}
Setup action
And then we can setup variables for the action itself. The highlight is that I'm using matrix.docker to define which subfolder in the repo I am going to build docker containers from (each of these subfolder should have a Dockerfile file).
jobs:
build:
timeout-minutes: 20
runs-on: ubuntu-latest
strategy:
matrix:
docker: ["single_cell", "graph_genome", "biotools", "hla", "assemble"]
permissions:
contents: read
packages: write
Steps
standard steps
Some standard github action steps to includes are:
actions/checkout@v3: checking out the repodocker/login-action: to login to theghcr.iocontainer registry, some more info can be found [here]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
identifying the new changes
- the
tj-actions/changed-fileshelps identifying what files are changed. And we can couple this with the${{ matrix.docker }}/Dockerfilevariable to determine if there are any changes being made to each docker file.
- name: Get changed files in the ${{ matrix.docker }} folder
id: changed-files-specific
uses: tj-actions/changed-files@v34
with:
files: |
${{ matrix.docker }}/Dockerfile
Building the docker container
- we can use the standard
docker/build-push-action, but adding aif: steps.changed-files-specific.outputs.any_changed == 'true'to use the above step to identify whether the build step is required for this container:
- name: Build ${{ matrix.docker }}
uses: docker/build-push-action@v2
if: steps.changed-files-specific.outputs.any_changed == 'true'
with:
context: ./${{ matrix.docker }}
file: ./${{ matrix.docker }}/Dockerfile
platforms: linux/amd64
push: true
tags: |
ghcr.io/${{ env.IMAGE_NAME_BASE }}/${{ matrix.docker }}:${{ github.sha }}
ghcr.io/${{ env.IMAGE_NAME_BASE }}/${{ matrix.docker }}:latest