Setting up Dockerfile & GitHub Workflow

Hesamyan
3 min readJan 30, 2021

Here I want to tell my experience with Docker builder and GitHub Workflow. I had a React project developed using Next.js and stored in my GitHub account for a while, so it came to my mind to fiddle with this repository using:

  • Dockerfile — for instructing Docker Daemon how to construct our Docker image through a given folder.
  • GitHub Workflow — instructing GitHub upon “push” or “pull-request” triggers some set of actions like building a new Docker image and pushing it to the DockerHub to name a few.

Using Docker Builder

For the sake of showing an example, I attached here my “Dockerfile”. Note that it should be inside the root directory of our project and also as a good practice I added a “.dockerignor”e file mentioning the “Dockerfile” to make the upcoming Docker image excluded from having a” Dockerfile”.

#Dockerfile
#
FROM node:latest
LABEL "Authour"="Hooman Hesamyan"
LABEL "Name"="CV"
RUN mkdir -p home/app
WORKDIR home/app
COPY . .
RUN npm install
RUN npm run build
EXPOSE 3000
CMD ["npm","run","start-loc"]

I added, “start-loc” metadata inside the “package.json” besides the “start” in order to maintain compatibility of the repository with Heroku which uses “start” tag that has ” -p $PORT “ as a directory to guide application to the serving port number.

#package.json
#
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start -p $PORT",
"start-loc": "next start"
}

I also included “next.config.js” to provide a hint to next.js builder script to spit out its output into “build” folder instead of “.next” folder by default.

#next.config.js
#
module.exports = {
distDir: 'build',
}

Using GitHub Workflow

We are all set and able to simply in our local machine make our Docker image. To do so, running the following command to build our Docker image is applicable.

docker build -t [IMAGE_TAG] -f [. | $PROJECT_PATH]

Eventually, we can easily push it to the DockerHub right inside our account and its appropriate repository. However, it seems tedious especially if we iterate over the application code several times.

What can we do? You guessed it, we can set GitHub upon each push (and also the other events as well) to do all these operations on behalf of us, but how?

The answer is very simple, what we need to do is to set a ‘yml’ file in a specific path and leave everything for the GitHub Actions to do for us.

[ROOT_DIRECTORY]/.github/workflows/[WORKFLOW_IDENTIFIER.yml]

Here you can find the content of my ‘yml’ file as an example, that is nothing just a set of instructions for GitHub to act what I intended to do manually.

Thanks to the biggest Pro of the ‘yml’ format which is “readability” we can interpret this file directly. For instance, metadata ‘on’ calls for the GitHub actions/events and ‘runs-on’ selects which operating system we want GitHub to process on.

There is a ‘steps’ tag that is actually a list and comprised of several other metadata. The ‘name’ tag is an identifier, ‘uses’ tag invokes external GitHub Actions, and ‘with’ tag represents environmental-like data for the Action.

name: Dockerhub CDon:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-lateststeps:
- name: Set up QEMU
uses: docker/setup-qemu-action@v1

- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and Push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
tags: hesamyan/hooman-cv:latest

Please note that “docker/login-action@v1” and “docker/build-push-action@v2” are available in GitHub Action-Store and are meant to make all login/push actions into DockerHub as simple as possible. With a simple search, you can find whatever you want in GitHub Actions-Store.

Now, if everything goes well, we can assume that upon any push we can deliver the Docker image of our application into DockerHub instantly.

Misc

Because of the fact that our code — especially ‘yml’ file, is going to be public, and as a best practice, I used GitHub Secrets in order for revealing my credential once it was needed in CI/CD procedure only.

My repository:

My DockerHub repository:

--

--