In my previous blog, you read about building containers with GitHub Actions and pushing them to Docker Hub. In this post, I’ll extend the workflow to push the containers to the GitHub Packages registry.
Why Use GitHub Packages
GitHub Packages is a software package hosting service, similar to npmjs.org, rubygems.org, or hub.docker.com. It allows you to host your packages and code in one place, privately or publicly, and use them as dependencies in your projects.
GitHub uses the README file in your repository to generate a description and details about the package or installation process. For each package version, GitHub adds metadata, including links to the author, repository, commit SHA, version tags, and date.
So Why Use GitHub Packages Over Docker Hub?
- If you use GitHub to store your Dockerfile in git, then it makes sense to use GitHub Packages, as it allows you to have everything in one place.
- If you use GitHub Actions for CI/CD, you can leverage Packages in your workflows.
- If you use other package formats, like npm or rubygems, you can use the same technology to store the packages.
Changing the GitHub Action Workflow
You have to be authenticated to push to a Docker repository. In the current workflow, we have a step called Docker Registry
, which looks like this
- name: Docker Registry
env:
DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }}
run: docker login -u $DOCKER_USERNAME -p $DOCKER_ACCESS_TOKEN
If no server is specified, the default setting for the Docker application is to return the value defined by the daemon. Thus, we have to update the above code example to the following:
- name: Docker Registry
env:
DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }}
run: docker login -u $DOCKER_USERNAME -p $DOCKER_ACCESS_TOKEN $DOCKER_REGISTRY
We then set this new environment variable at the env
block and provide it with the correct server.
DOCKER_REGISTRY: docker.pkg.github.com
As the values for DOCKER_USERNAME
and DOCKER_ACCESS_TOKEN
are different for GitHub Packages, we also need to update the repository secrets with the new values.
The tagging needs to follow the following pattern docker.pkg.github.com/owner/repository/image_name:version
. Note that this is different from the pattern we currently use. We should change the run
step of the Building Docker Image
build, as follows.
- name: Building Docker Image
run: |
# Change all uppercase to lowercase
REPOSITORY=$(echo $GITHUB_REPOSITORY | tr '[A-Z]' '[a-z]')
docker build --build-arg HUGO_VERSION=$HUGO_VERSION --no-cache \
-t $DOCKER_REGISTRY/$REPOSITORY/hugo-docker:$HUGO_VERSION-$GITHUB_RUN_ID \
-t $DOCKER_REGISTRY/$REPOSITORY/hugo-docker:latest .
Here, we remove the $DOCKER_USERNAME
and start to use the $GITHUB_REPOSITORY
variable, which GitHub provides as a default. It contains the owner and repository name — in our case, PaulusTM/hugo-docker
. The uppercase characters are a problem for Docker, so we need to transform them to lowercase.
The last change is the Docker push step. We need to remove $DOCKER_USERNAME
here as well and use the same lowercase transformation for the $GITHUB_REPOSITORY
variable.
- name: Push Docker Container to Registry
run: |
# Change all uppercase to lowercase
GITHUB_REPOSITORY=$(echo $GITHUB_REPOSITORY | tr '[A-Z]' '[a-z]')
docker push $DOCKER_REGISTRY/$GITHUB_REPOSITORY/hugo-docker
If we push these changes to the repo and wait until the workflow is complete, you’ll see that we now have one package included within the repository.
You can host multiple packages in the same repository. You can also build several versions of the same container and have them all available next to your codebase.
The packages are also visible on your profile page so people can find all packages that are published in one simple overview.
Package Details
The images hosted on GitHub include details and download statistics, along with their entire history, reference command to pull the image, and instructions for using it as a base image in a Dockerfile.
Keep in mind that you can’t delete packages that you push to registry. GitHub restricts this action so that you don’t break projects that depend on your package.
Webhooks
If you want to use GitHub Webhook to trigger a follow-up build, then you can use RegistryPackageEvent
. This could be useful if you are using tools like Jenkins or Kubernetes and want to trigger a new deployment every time your package is published in GitHub Packages.
My Thoughts on GitHub Packages
I hope that after reading this, you’ll try out Github Packages for yourself. It is easy to get started, and it provides a nice overview of available packages for your project so new users can find the packages easily