Github Actions

It sure can be a hassle to put docker push corydonbaylor/images:flask everytime we want the app to get to docker. It really is unbearable. Luckily there is a way to automatically deploy to docker hub each time you merge onto main.

Enter the magic of GitHub actions.

Setting Up

This may come as a shock but we need to create a GitHub repo for this to work. Let's do that now. I like to create it on GitHub and then clone it in.

git clone [email protected]:corydonbaylor/flask-docker.git

Next, in the base of our folder we need to create a folder called .github/workflows:

mkdir .github
cd .github
mkdir workflows

Finally, let's put our stuff in from when we built our flask app. The directory tree should look like this:

├── Dockerfile
│   ├── .github
│   │   ├── workflows
├── README.md
├── app.py
└── requirements.txt

The Actual Action

Ok within the workflows directory, create a file called docker-publish.yml and put all of this in it:

name: Build and Push Docker Image

on:
  push:
    branches:
      - main  

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Log in to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build the Docker image
        run: |
          docker build -t corydonbaylor/images:flask .  

      - name: Push the Docker image
        run: |
          docker push corydonbaylor/images:flask  

Let's break down what's happening here:

The Trigger: this is what triggers this pipeline to run. In our case, it's when we push to the main branch.

on:
  push:
    branches:
      - main  # Change this to your default branch if it's different

Setting Up the Pipeline: this determine what the steps in the operating system will be running on. In our case, that is the latest version of ubuntu.

jobs:
  build:
    runs-on: ubuntu-latest

Getting the Code: the first step in the pipeline checks out the code from the repo.

steps:
  - name: Checkout code
    uses: actions/checkout@v2

Logging into Docker: Next we are going to log into docker. In order to do this you will need to add your username and password as secrets.

To do this go Repository Settings > Security > Secretes and Variables > Actions and add your username and password.

- name: Log in to Docker Hub
  uses: docker/login-action@v2
  with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_PASSWORD }}

Build and Push the Image:

- name: Build the Docker image
  run: |
    docker build -t corydonbaylor/images:flask .  # Replace with your image name

- name: Push the Docker image
  run: |
    docker push corydonbaylor/images:flask  # Replace with your image name

Why Do This At All?

Ok so why are we even doing this? It's all about making your code entirely portable. If another person or program wants to pick up your code they should be able to do that.

This does not need to be the last step of the process either. Perhaps something like Tekton picks up the image you pushed and uses as part of its CICD process. Perhaps a hosting service picks up the latest image and then uses that to serve your website.

The possibilities are endless.