New month new blog post.... 🚀🚀
Introduction
In this tutorial, we will be building a Docker image of an existing project and pushing it to Docker Hub using GitHub Actions. We will be using the following technologies:
- Docker
- Git and GitHub (obviously)
- GitHub Actions
- Docker Hub
Overview
The Problem ☢️
We want to build a Docker image and push it to Docker Hub whenever we push to the main
branch. We also want to build a Docker image and push it to GitHub Packages whenever we push to the dev
branch. We want to do this automatically using GitHub Actions. We want to be able to do this without exposing our Docker Hub credentials.
The Solution ⚡
We will use GitHub Actions to build and push Docker images to Docker Hub. We will use the following steps:
- Create a workflow file.
- Add a job to build and push the Docker image to Docker Hub.
- Commit and push the changes to the
dev
branch. - Specify our docker crenentials as secrets in the repository settings.
- Open a pull request to merge the
dev
branch into themain
branch. - Watch the workflow run and verify that the Docker image is pushed to Docker Hub.
Prerequisites 📃
- A GitHub account.
- A Docker Hub account.
- Docker installed on your machine. You can follow the official documentation to install Docker on your machine.
- A GitHub repository with a Dockerfile and a project that you want to build and push to Docker Hub.
Step 1: Create a workflow file 🏊
All GitHub Actions workflows are defined in YAML files in the .github/workflows
directory of your repository.
We'll stary by creating a workflow file for building and pushing the Docker image to Docker Hub.
Create a file named .github/workflows/docker-hub.yml
in your repository. This file will contain the workflow that we will use to build and push the Docker image. The workflow will be triggered whenever we push to the main
or dev
branch. We will also specify the Docker image name and tag. We will use the following workflow:
name: Build and Push Docker Image to Docker Hub
on:
push:
branches: [ "dev", "main" ]
pull_request:
branches: [ "dev", "main" ]
env:
# Use docker.io for Docker Hub if empty
REGISTRY: docker.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build the Docker image
run: docker-compose build --no-cache --force-rm
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Test the Docker image
run: docker-compose up -d
push_to_registry:
name: Push Docker image to Docker Hub
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to Docker Hub
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: "{{defaultContext}}"
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
Lets break down the workflow file:
-
name
: The name of the workflow. -
on
: The events that trigger the workflow. We will trigger the workflow whenever we push to themain
ordev
branch. -
env
: The environment variables that we will use in the workflow. We will use the following environment variables:-
REGISTRY
: The registry that we will use to push the Docker image. We will usedocker.io
for Docker Hub. -
IMAGE_NAME
: The name of the Docker image. We will use the name of the repository as the name of the Docker image.
-
-
jobs
: The jobs that will run in the workflow. We will use the following jobs:-
build
: The job that will build the Docker image. We will use the following steps: -
Checkout
: We will use the actions/checkout action to checkout the repository. -
Build the Docker image
: We will use thedocker-compose build
command to build the Docker image. We will use the--no-cache
and--force-rm
flags to ensure that we are building the Docker image from scratch. This will ensure that we are building the Docker image with the latest changes before pushing it to Docker Hub.
-
-
test
: The job that will test the Docker image. We will use the following steps:-
Checkout
: We will use the actions/checkout action to checkout the repository. -
Test the Docker image
: We will use thedocker-compose up -d
command to test the Docker image. We will use the-d
flag to run the Docker image in the background.
-
-
push_to_registry
: The job that will push the Docker image to Docker Hub. We will use the following steps:-
Check out the repo
: We will use the actions/checkout action to checkout the repository. -
Set up Docker Buildx
: We will use the docker/setup-buildx-action action to set up Docker Buildx. -
Log in to Docker Hub
: We will use the docker/login-action action to log in to Docker Hub. We will use the following inputs: -
username
: The username of the Docker Hub account. We will use theDOCKER_USERNAME
secret. -
password
: The password of the Docker Hub account. We will use theDOCKER_PASSWORD
secret. -
Extract metadata (tags, labels) for Docker
: We will use the docker/metadata-action action to extract the metadata for the Docker image. We will use the following inputs: -
images
: The name of the Docker image. We will use theREGISTRY
andIMAGE_NAME
environment variables.
-
-
Build and push Docker image
: We will use the docker/build-push-action action to build and push the Docker image to Docker Hub. We will use the following inputs:-
context
: The context of the Docker image. We will use thedefaultContext
variable. -
push
: A boolean value that specifies whether to push the Docker image to Docker Hub. We will set this totrue
. -
tags
: The tags of the Docker image. We will use thetags
output of thedocker/metadata-action
action. -
labels
: The labels of the Docker image. We will use thelabels
output of thedocker/metadata-action
action.
-
Step 2: Create a dev
branch and commit the changes to the dev
branch 🌿
Create a dev
branch and commit the changes to the dev
branch. This will allow us to test the workflow before merging the changes to the main
branch. We will use the following commands:
git checkout -b dev
git add .
git commit -m "Add workflow to build and push Docker image to Docker Hub"
Step 3: Push the changes to the dev
branch 🧑💻
Create a Github Repository if you dont already have one and push the changes to the dev
branch. We will use the following commands:
git add .
git commit -m "Add workflow to build and push Docker image to Docker Hub"
git push -u origin dev
Step 4: Specify our docker credentials as secrets in the repository settings 🔐
We will specify our Docker Hub credentials as secrets in the repository settings. We will use the following secrets:
-
DOCKER_USERNAME
: The username of our Docker Hub account. -
DOCKER_PASSWORD
: The password of our Docker Hub account.
This will allow us to use the credentials in the workflow file without exposing them. Thus keeping sensitive information secure. This gives the workflow access to the Docker Hub account. As well ability to use the workflow across multiple repositories.
Step 5: Open a pull request to merge the dev
branch into the main
branch 🛣️
Once the workflow successfully runs on the dev
branch, we can merge the changes to the main
branch. Open a pull request to merge the dev
branch into the main
branch. This will trigger the workflow. The workflow will run on the main
branch and push the Docker image to Docker Hub. Example of successful workflow run on open pull request:
Step 6: Watch the workflow run 📺
Watch the workflow run and verify that the Docker image is pushed to Docker Hub. Login to Docker Hub and check if the image is successfully pushed to Docker Hub. The image should be pushed to Docker Hub with the appropriate tags. for example kenmwaura1/fastapi-vue:main
and kenmwaura1/fastapi-vue:sha-<sha>
. Example of successful workflow run on merge pull request:
Screenshot of workflow running on merge pull request:
Step 7: Verify that the Docker image is pushed to Docker Hub 🐋
Login to Docker Hub and check if the image is successfully pushed to Docker Hub. The image should be pushed to Docker Hub with the appropriate tags. for example kenmwaura1/fastapi-vue:main
and kenmwaura1/fastapi-vue:sha-<sha>
. Example of image pushed to Docker Hub:
GitHub Repo for this tutorial 🐙
Find the sample code for this workflow in the following GitHub repository:
KenMwaura1 / Fast-Api-Vue
Simple asynchronous API implemented with Fast-Api framework utilizing Postgres as a Database and SqlAlchemy as ORM . GiHub Actions as CI/CD Pipeline. Vue + Daisy UI for the frontend
FastAPI Vue Starter App
This repository contains code for asynchronous example api using the Fast Api framework ,Uvicorn server and Postgres Database to perform crud operations on notes.
Accompanying Article
Installation method 1 (Run application locally)
-
Clone this Repo
git clone (https://github.com/KenMwaura1/Fast-Api-example)
-
Cd into the Fast-Api folder
cd Fast-Api-example
-
Create a virtual environment
python3 -m venv venv
-
Activate virtualenv
source venv/bin/activate
For zsh users
source venv/bin/activate.zsh
For bash users
source venv/bin/activate.bash
For fish users
source venv/bin/activate.fish
-
Cd into the src folder
cd src
-
Install the required packages
python -m pip install -r requirements.txt
-
Start the app
python main.py
7b. Start the app using Uvicorn
uvicorn app.main:app --reload --workers 1 --host 0.0.0.0 --port 8002
-
Ensure you have a Postgres Database running locally Additionally create a
fast_api_dev
database with user**fast_api**
having required privileges. OR Change the DATABASE_URL variable in the .env file inside thenapp
folder to reflect database settings (user:password/db) …
Find the docker image on Docker Hub: Fastapi-Vue
Conclusion 🫔
In this tutorial, we learned how to build and push Docker images to Docker Hub and GitHub Packages using GitHub Actions. We also learned how to specify our Docker Hub credentials as secrets in the repository settings.
Next Steps
On the next tutorial, we will learn how to build and push Docker images to GitHub Packages using GitHub Actions. Stay tuned!
Top comments (2)
Informative ✌.
Thank you for reading through!