Streamlining Docker Image Deployment to GitHub Container Registry with GitHub Actions

th@n@n
3 min readFeb 5, 2024

In the realm of DevOps and continuous integration, automating the deployment process is crucial for maintaining a seamless and efficient workflow. GitHub Actions provides a powerful platform for automating various tasks, and in this blog post, we’ll dive into a comprehensive workflow designed to upload Docker images to the GitHub Container Registry (ghcr.io).

Prerequisites

Before implementing this workflow, ensure that you have the following:

  • A GitHub repository containing Dockerized application code.
  • GitHub Container Registry set up for the repository.
  • Dockerfile within the repository.

Understanding the Workflow

The GitHub Actions workflow is defined in a YAML file, below are the detailed explanation of each steps

name: Upload images to GitHub Container Registry
on:
push:
branches:
- main
tags:
- 'v*'

This section specifies that the workflow should run on each push to the main branch and on tags matching the pattern 'v*'.

jobs:
deploy-to-container-registry:
runs-on: ubuntu-latest
permissions:
packages: write
contents: write
steps:
- name: Checkout Repository
uses: actions/checkout@v4

The workflow defines a job named deploy-to-container-registry, which runs on the latest version of Ubuntu. It also specifies the necessary permissions to write to packages and contents.

            - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

This step sets up Docker Buildx, a CLI plugin for building multi-platform Docker images.

            - name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}

tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha

The docker/metadata-action step generates metadata for Docker images, defining images, tags, and labels based on different events.

            - name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

This step logs in to the GitHub Container Registry using the GitHub Token for authentication. You can use the PAT token as well

            - name: Build a Docker images
if: ${{ github.ref_type == 'tag' }}
run: |
export version=$(echo ${{ github.ref_name }} | tr -d v)
docker build -t ghcr.io/${{ github.repository }}:$version .
docker images
docker run --name nginx-html -d -p 8080:80 \
ghcr.io/${{ github.repository }}:$version

If the push event is a tag, this step builds the Docker image, tags it with the version, and runs a container for testing.

            - name: Test a docker image    
run: |
curl -I http://localhost:8080/index.html | grep -i nginx

This step tests the deployed Docker image by making a simple HTTP request.

            - name: Push Docker image
if: ${{ github.ref_type == 'tag' }}
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

If the push event is a tag, this step pushes the Docker image to GitHub Container Registry with the specified tags and labels.

Here is the full YAML file

name: Upload images to github container registry
on:
push:
branches:
- main
tags:
- 'v*'
jobs:
deploy-to-container-registry:
runs-on: ubuntu-latest
permissions:
packages: write
contents: write
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/${{ github.repository }}

tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha


- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}



- name: Build a Docker images
if: ${{ github.ref_type == 'tag' }}
run: |
export version=$(echo ${{ github.ref_name }} | tr -d v)
docker build -t ghcr.io/${{ github.repository }}:$version .
docker images
docker run --name nginx-html -d -p 8080:80 \
ghcr.io/${{ github.repository }}:$version

- name: Test a docker image
run: |
curl -I http://localhost:8080/index.html | grep -i nginx

- name: push Docker image
if: ${{ github.ref_type == 'tag' }}
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

you can find the latest working code here

Conclusion

By implementing this GitHub Actions workflow, you’ve automated the deployment of Docker images to the GitHub Container Registry, making your development workflow more efficient. The workflow ensures that images are built, tested, and pushed to the registry seamlessly, providing a reliable and consistent deployment process.

If you liked this blog, then please like and follow me

Happy learning

--

--

th@n@n

TestOps Specialist: Bridging DevOps and Automated Testing for seamless integration and high-quality software delivery. 🚀