How to Publish Releases to Docker Hub using GitHub Actions
Dolt is a version controlled relational database. It is a combination of Git and MySQL. We've received requests for an official Dolt Docker image from many customers who want to run Dolt in a container. We give our customers what they ask for, no matter what. 😎 Today, we announce our official Docker Images on Docker Hub.
dolthub/dolt
gives you a container with Dolt installed and is equivalent to running thedolt
command.dolthub/dolt-sql-server
runs a server in the container. It can be mounted with your local directory for storing your data locally and can be connected from the host system through port-mapping.
In this blog, we see how to build and push Docker Images both locally and through GitHub Actions. The examples are for
building the dolthub/dolt
image.
Let's look at how we publish Docker images locally
This is a quick guide on how to build and push Docker images from a local machine. First, we need a Dockerfile from which to build an image. Below is a simple Dockerfile for installing Dolt.
FROM ubuntu:22.04
ARG DOLT_VERSION
ADD https://github.com/dolthub/dolt/releases/download/v${DOLT_VERSION}/dolt-linux-amd64.tar.gz dolt-linux-amd64.tar.gz
RUN tar zxvf dolt-linux-amd64.tar.gz && \
cp dolt-linux-amd64/bin/dolt /usr/local/bin && \
rm -rf dolt-linux-amd64 dolt-linux-amd64.tar.gz
ENTRYPOINT ["/usr/local/bin/dolt"]
To build a Docker image, we run the command below from the directory that the Dockerfile is in. This command builds
an image named dolt
with the tag name latest
using the Dockerfile above and a build argument of DOLT_VERSION=0.50.8
.
The -t
flag gets a value of <image_name>:<tag_name>
, and we provide an argument DOLT_VERSION
with any Dolt
version we want. This is used to download a specific Dolt version for the image. Defining the
the exact version of Dolt is a good practice because it lets us pin to the exact version we want, without worrying that future builds will pull in a new version we might not be expecting.
$ docker build -t dolt:latest --build-arg DOLT_VERSION=0.50.8 -f Dockerfile .
Now, we have built our image. We can use the image to run any dolt CLI commands on the host system. Running the image
with argument version
is equivalent as running dolt version
if dolt was installed on our local machine. This
verifies that the version we specified to build the image was successfully installed in the container.
$ docker run dolt:latest version
dolt version 0.50.8
no valid database in this directory
This is a simple example of how we can create Docker image locally and run it. If we want to publish our image, we
can simply push the image we created locally to Docker Hub. To do this, we need to be logged in to Docker Hub and make
sure the image name has the <user_name>/<image_name>:<tag_name>
pattern with the user_name
that is used to log in
to Docker Hub. Since we did not create the initial image with the username specified like this, we need to create a new image
with an appropriate name before we can push it to our Docker Hub account.
$ docker build -t jennifersp/dolt:latest --build-arg DOLT_VERSION=0.50.8 -f Dockerfile .
$ docker push jennifersp/dolt:latest
Now, we can see the Dolt Docker image was successfully pushed to Docker Hub.
Let's automate Docker image push with GitHub Actions
I personally experienced how easy and flexible using GitHub Actions is, compared to setting up automated builds on Docker Hub for an organization's repository. I basically spent a week trying to figure out the whole process with automated builds including building the Dockerfile. This is from someone who was unfamiliar with Docker to begin with.
The goal is to create a GitHub Actions job that builds and pushes the Docker image on every release of Dolt. A little bonus
addition to it is that we want to support multiple architectures for our customers, who need linux/amd64
and linux/arm64
.
Here is breakdown of the yaml file for GitHub Actions to build and push the Docker image.
- We give the GitHub Actions job a good name that will be displayed on Actions tab of GitHub repository
name: Push Docker Image to Docker Hub
- We require an input for the Dolt version number we want to create the image with.
on:
workflow_dispatch:
inputs:
version:
description: 'SemVer format release tag, i.e. 0.24.5'
required: true
repository_dispatch:
types: [ push-docker-image ]
- The last part is the list of steps to take in the GitHub Actions job.
- It starts with checking out the latest version of GitHub repository under workspace.
- Next, it logs into DockerHub using previously set secrets on GitHub, so it's kept secure and ready to be used. This is a part that lead me to try out automated builds on DockerHub instead of GitHub Actions job. I will include why I tried using DockerHub automated builds web UI and ended up not using it at the end of the blog.
- After getting logged in to Docker Hub, we need to set up QEMU, which allows us to build images for different architectures on a single machine regardless of its architecture. In our case, it allows us to build images for
linux/amd64
andlinux/arm64
on alinux/amd64
system. - Then, it sets up Docker Buildx tool. This is an experimental tool, and it needs specific setup to run locally. I did not find any guide on how to enable this mode on docker documentations, but I found this GitHub README, which was helpful.
- Finally, it builds and pushes the image at the same time. This step builds the image using two specified platforms, the Dockerfile and tag names we want to publish. In our case, we want to update and push
latest
tag and create new tag with the new release version. - The last step is to update the README on our Docker Hub repository with specified path to file that we want to use.
jobs:
docker-image-push:
name: Push Docker Image
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
with:
platforms: linux/amd64,linux/arm64
- name: Build and push dolt image
uses: docker/build-push-action@v3
with:
platforms: linux/amd64,linux/arm64
context: .
file: ./docker/Dockerfile
push: true
tags: dolthub/dolt:${{ github.event.inputs.version || github.event.client_payload.version }} , dolthub/dolt:latest
build-args: |
DOLT_VERSION=${{ github.event.inputs.version || github.event.client_payload.version }}
- name: Update Docker Hub Readme for dolt image
uses: peter-evans/dockerhub-description@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
repository: dolthub/dolt
readme-filepath: ./docker/README.md
I have broken down a single file into three section above. The source of these files can be found in Dolt repository.
With above GitHub Actions job, let's use the same Dockerfile we used to publish the image locally. We can use
this Dockerfile for building images for both amd64
and arm64
architectures. BUILDPLATFORM
and BUILDARCH
is
a global environment variable that is defined during build depending on the platform the image is build on.
For example, when building image for platform,linux/amd64
, the values are set as BUILDPLATFORM=linux/amd64
and BUILDARCH=amd64
. This allows us to install the correct binary distributor to be installed in the container on
specific platform.
FROM ubuntu:22.04
ARG DOLT_VERSION
ARG BUILDARCH
ADD https://github.com/dolthub/dolt/releases/download/v${DOLT_VERSION}/dolt-linux-${BUILDARCH}.tar.gz dolt-linux-${BUILDARCH}.tar.gz
RUN tar zxvf dolt-linux-${BUILDARCH}.tar.gz && \
cp dolt-linux-${BUILDARCH}/bin/dolt /usr/local/bin && \
rm -rf dolt-linux-${BUILDARCH} dolt-linux-${BUILDARCH}.tar.gz
ENTRYPOINT ["/usr/local/bin/dolt"]
Why GitHub Actions is better
I first set up the 'organization' account for dolthub
, but I did not find where the access token was for this account,
so I thought it was not possible to make a GitHub Actions job to push images to the organization repository.
What made me more convinced was that there is automated builds set up web UI on Docker Hub. It was definitely
challenging as there is very little Docker documentation for how I can use automated builds on the Docker Hub web UI for
organization repositories. I like to look at examples and follow along to understand usages of some features.
This took a while for me to get something working, and when I was finishing up, I got stuck with not being able
to disable the root README of GitHub dolt repository from updating the Docker Hub dolt repository README.
This was frustrating because I found I could use .dockerignore
to ignore the README in the root, but it
does not work for automated builds. Another downside of using the Docker Hub web UI for automated builds was that it
needed a lot more files including pre- and post-build scripts and separate Dockerfiles for each platform I wanted to
support.
This is why I had to look for a different way to resolve this and came back to a GitHub Actions job, which I initially thought was not possible. The good part is that I learned a lot about both the case of automated build and pushing Docker images either through Docker Hub or through GitHub Actions.
If you're interested in learning more about Dolt, try out our Docker Images. If you have any questions about Dolt, join our Discord channel to chat with our team.