Learn how to CI/CD with GitHub Actions and Docker

Originally published by Abhinav Dhasmana at https://blog.bitsrc.io

This article will cover the following:

  • Use Docker instead of bare metal deployment
  • Use GitHub actions for continuous integration of your app
  • Use GitHub actions for continuous deployment by pushing the Docker image to a Docker registry (Docker Hub)

Our workflow will look like this

A workflow of a Node.js app deployed using GitHub actions

The complete source code is available on GitHub

Use Docker instead of bare metal deployment

Dockerizing an existing app is easy. All we need is a Dockerfile and an optional .dockerignore file. Below is a Dockerfile for our app.

FROM node:10.16.0-alpine

WORKDIR /source/github-action-example-node

COPY package.json /source/github-action-example-node

RUN cd /source/github-action-example-node && npm i --only=production

COPY . .

EXPOSE 3000
CMD [“sh”, “-c”, “node server.js”]

It copies our package.json, runs npm install and starts the server. To make sure our file is correct, we can run docker build -t abhinavdhasmana/github-action-example-node . from the root folder. If we run docker images , we will see our latest image. We can also run our container with docker run -d -p 3000:3000 abhinavdhasmana/github-action-example-node. Point the browser to http://localhost:3000/ and text will appear.

What are GitHub Actions and how do they work

‘GitHub Actions’ is an API that can react to any event, GitHub’s or our own events. For example, for every push event on the repository, we want our test cases to run.

For GitHub Actions to work, we need to create a .github/workflows folder. We need to create our workflows inside this folder. Let’s create push.yml. Here is what we want from our workflow:

On every push, perform these actions in the given order

  1. git clone the repo
  2. run npm install
  3. run npm lint
  4. run npm test
  5. build the docker image
  6. login to docker hub
  7. Push the image to docker hub

Since we have to run each of these commands inside a docker we have to declare a Dockerfile for each of these actions and run the command in those containers. This is, of course, very tedious and error-prone. Remember, GitHub Actions are code, so we can just reuse, edit and fork them as we do with any other piece of code.

This is how our push.yml would look like

on: push
name: npm build, lint, test and publish
jobs:
build-and-publish:
name: build and publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: npm install
uses: actions/npm@master
with:
args: install
- name: npm test
uses: actions/npm@master
with:
args: run test
- name: npm lint
uses: actions/npm@master
with:
args: run lint
- name: docker build
uses: actions/docker/cli@master
with:
args: build -t abhinavdhasmana/github-action-example-node .
- name: docker login
uses: actions/docker/login@master
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
- name: docker push
uses: actions/docker/cli@master
with:
args: push abhinavdhasmana/github-action-example-node

GitHub actions file for npm actions and push to docker hub

Let’s dissect this file

line 1: We want to trigger our workflow when someone pushes the code to our repo

line 3–6: We are defining a job build-and-publish which runs on ubuntu-latest. Each job runs in a fresh instance of a virtual environment. A job can contain one or more steps .

line 8: This is step 1 of our application. Here we want to get our source code. We can write our own code to pull our source code or reuse an open source. The repo link is https://github.com/actions/checkout

line 9-12: This is step 2 of our workflow where we run npm install on our codebase. Again, we use an open source action at https://github.com/actions/npm and pass install as an argument.

line 13–20: These are same as the last step except the argument passed to npm command.

line 21–24: We build a docker image of our code with the help of docker action and tag the image as abhinavdhasmana/github-action-example-node

line 25-29: This one is a little different where we want to login into docker hub. Here we use secrets which are passed as an env variables to our build. We can set these env variables in many ways. To set this up via GitHub, go to Settings-> Secrets and create new secrets

Store secrets in GitHub

line 30-33: We push the image to the docker hub with the tag we created in line 24.

If we commit these changes, GitHub Actions will come into play and start running all the steps in our job. We should see something like this

GitHub Actions running our job

To validate if a new image has been pushed to DockerHub, we should see a new image being pushed in Docker Hub

Docker Hub image

Full source code is available on GitHub.

Thanks for reading

If you liked this post, share it with all of your programming buddies!

Follow me on Facebook | Twitter

Further reading

Docker and Kubernetes: The Complete Guide

Docker Mastery: The Complete Toolset From a Docker Captain

Docker for the Absolute Beginner - Hands On - DevOps

Docker for Absolute Beginners

How to debug Node.js in a Docker container?

Docker Containers for Beginners

Deploy Docker Containers With AWS CodePipeline

Build Docker Images and Host a Docker Image Repository with GitLab

How to create a full stack React/Express/MongoDB app using Docker



#docker #node-js #devops #github

Learn how to CI/CD with GitHub Actions and Docker
170.80 GEEK