Building and deploying Docker images with GitHub Actions
Slowly moving my projects from a selfhosted GitLab instance to GitHub, while doing so I'm learning how to use GitHub Actions to build and delpoy Docker images to the GitHub Container Registry (ghcr.io).
After having most of my personal projects hosted on a Docker server at home, I decided to move everything out again after a power outage and multiple fiber outages.
One of the steps involved is moving projects from a self hosted GitLab instance to GitHub and using GitHub Actions to build and deploy Docker images to the GitHub Container Registry (ghcr.io).
In this blog post I will show you how to build and deploy a Docker image to the GitHub Container Registry using GitHub Actions. I’ll use the workflow used to build and deploy this website as an example to get you started with GitHub Actions and Docker.
Website repository: github.com/jeroenvanwissen/jeroenvanwissen.nl
Create a Dockerfile
First, create a Dockerfile in the root of your repository. This file will be used to build the Docker image. Here is the Dockerfile used to build the Docker image of this website, which is an Astro.build application deployed using Nginx:
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY ./conf/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
HEALTHCHECK --start-period=30s --interval=5m --timeout=1s --retries=5 CMD curl -sf http://localhost/health || exit 1
CMD ["nginx", "-g", "daemon off;"]
This Dockerfile uses a multi-stage build to first build the Astro.build application using Node.js, and then copies the built files to an Nginx container. The Nginx container serves the static HTML files generated by the Astro.build application.
Create a GitHub Actions workflow
Next, create a GitHub Actions workflow file in the .github/workflows
directory of your repository. This file will define the steps to build and deploy the Docker image. Here is the GitHub Actions workflow file used to build and push the Docker image of this website to the GitHub Container Registry:
name: Build and push Docker image to ghcr.io
on:
push:
tags: [ 'v*.*.*' ]
env:
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/[email protected]
- name: Set up Docker Buildx
uses: docker/[email protected]
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/[email protected]
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/[email protected]
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
id: build-and-push
uses: docker/[email protected]
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: |
${{ steps.meta.outputs.tags }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
labels: ${{ steps.meta.outputs.labels }}
This GitHub Actions workflow file defines a workflow that is triggered when a new tag is pushed to the repository. It uses the docker/build-push-action
action to build and push the Docker image to the GitHub Container Registry. It tags the image in the registry with the given version tag AND ‘latest’ tag, so the latest versionned image will always have the ‘latest’ tag. The workflow logs into the registry using the GitHub token, which is automatically provided by GitHub Actions.
Trigger the workflow
Now that you have created the Dockerfile, GitHub Actions workflow, you can trigger the workflow by adding a tag to your repository. Once the workflow is triggered, it will build the Docker image and push it to the GitHub Container Registry.
To use this Docker image in my Docker Compose file, I simply referenced the image:
...
services:
website:
image: ghcr.io/jeroenvanwissen/jeroenvanwissen.nl:latest
...
That’s it! You have successfully built and deployed a Docker image to the GitHub Container Registry using GitHub Actions. You can now use this workflow as a template for building and deploying other Docker images in your projects.
I hope this blog post was helpful to you. If you have any questions or feedback, feel free to contact me on Twitter/X or Mastodon. I’d love to hear from you!