Fabio
Posted on July 24, 2022
In this post, I will show how easily you can set up your own docker images and then utilize GitHub Actions to deploy them to a Docker registry. This will save you set up time and make your environments more stable.
Prerequisites
- Git installed and GitHub Account
- Docker installed (for testing)
Get Started with Docker
Docker is a virtualization tool which allows you to require an image which comes with pre-installed configurations and software. So you can pick an operating system of your liking (NO IOS that's illegal) and then get started with installing what you need. These definitions will be written into a Dockerfile. If you don't have docker installed, head to their docs it is really simple to install.
Write your first image
Let's start with a very simple Python image. We will pull the latest distribution of Python and set the PYTHONUNBUFFERED=1
to ensure that all python output is sent to the terminal for better debugging. Paste the below lines into a Dockerfile
(Yes the file has no file extension).
FROM python:latest
ENV PYTHONUNBUFFERED=1
Once you have the file, you can now run
docker build . --file Dockerfile -t ${Image_Name}
The --file
can be used in case your Dockerfile has not the default name or is in another path. The -t
flag is used to give the image a name. After the image build successfully on your machine, you can go ahead and try to publish it to hub.docker.com.
Next, we want to tag our image, therefore please create an account at docker hub. We will need the namespace. Before proceeding, please log in locally with docker login.
docker login --username ${USERNAME}
This will log you in and store an encrypted version of your credentials for later use locally.
To version our image we use tags, so if one image is bad due to any reason, you can always pull an earlier image. The following command will tag the image. The DOCKER_HUB_NAMESPACE
is by default your username in docker hub. So for me, it would be snakepy
.
docker tag "${IMAGE_NAME}" "${DOCKER_HUB_NAMESPACE}/${IMAGE_NAME}:${VERSION}"
Concrete example:
docker tag python-dev snakepy/python-dev:latest
After this, all what is left is to upload the image to docker hub, so you can use it later, therefore you need to run:
docker push "${DOCKER_HUB_NAMESPACE}/${IMAGE_NAME}:${VERSION}"
After you have uploaded your image, you can pull it from another Dockerfile and require it:
FROM ${DOCKER_HUB_NAMESPACE}/${IMAGE_NAME}:${VERSION}
WorkFlow for automation
I have created a repository where I upload my images to. The workflow is set up in a way that if I push to that repository it will automatically build all images and push them to docker hub with a new version. I also created scheduled tasks, which runs periodically to release the latest version of the image.
This is where the fun begins and once you have your automation set up you can refine it, and it will grow overtime. You can have a look at my current set up.
To automate the creation of docker images, you need to do the following steps:
- create a repository for your images
- set the secrets in the repository
- create workflow file
- profit 💰
First create the GitHub repository and then find the secrets tab, there you can add new secrets. You will need to add DOCKER_HUB_NAMESPACE
, DOCKER_HUB_PASSWORD
andDOCKER_HUB_USER
. You can either set them as repository or workflow env. I found it easier to simply set them as repository variable.
After you have added the secrets, we can proceed to the GitHub workflow file. The file(s) need to be inside .github/workflows
. In there I created two files, one for scheduled tasks and one if I push. This will help us to deal easier with the versioning of the images.
name: publish-to-docker-hub
on: [push]
env:
 DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
 DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }}
 DOCKER_HUB_NAMESPACE: ${{ secrets.DOCKER_HUB_NAMESPACE }}
 VERSION: ${{ github.sha }}
jobs:
publish_python:
runs-on: ubuntu-latest
env:
IMAGE_NAME: 'python-dev'
LANGUAGE: 'python'
LANGUAGE_VERSION: 3.10
steps:
- uses: actions/checkout@v2
- run: echo ${DOCKER_HUB_PASSWORD} | docker login --username "${DOCKER_HUB_USER}" --password-stdin
- run: docker build . --file ${IMAGE_NAME}/Dockerfile -t ${IMAGE_NAME}
- run: docker tag "${IMAGE_NAME}" "${DOCKER_HUB_NAMESPACE}/${IMAGE_NAME}:${LANGUAGE}${LANGUAGE_VERSION}-${VERSION}"
- run: docker push "${DOCKER_HUB_NAMESPACE}/${IMAGE_NAME}:${LANGUAGE}${LANGUAGE_VERSION}-${VERSION}"
First, we define the name of the workflow publish-to-docker-hub
and then the action trigger. Next, we define the variables which will be pulled from the GitHub secret store. Then we define our jobs. Under Jobs, you can have multiple jobs (checkout my YAML file). We are essentially doing what I showed before. We are logging into docker hub, building the image, tagging the image and uploading the image.
Please note my repository structure! Every Dockerfile is placed like this ${IMAGE_NAME}/Dockerfile
. This way I can write small documentations with it or even have config files which I can copy in during build time.
Now you should see that the action is created for every push you do. I also like an action once a month to release the latest version of the image, just to keep them fresh.
So I created a second workflow file which is essentially the same and the only difference is the trigger and the VERSION variable.
on:
 schedule:
  - cron: '0 0 1 * *'
env:
 DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
 DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }}
 DOCKER_HUB_NAMESPACE: ${{ secrets.DOCKER_HUB_NAMESPACE }}
 VERSION: latest
LET ME KNOW 🚀
- Do you need help, with anything written above?
- What will be your first Image? 😄
- Do you think I can improve - then let me know
- Did you like the article? 🔥
Check my laravel-dev image out! 🔥
Posted on July 24, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.