CI/CD using GitHub Actions, Build/Push Docker Image to Docker Hub

Abhay Ahire
5 min readFeb 26, 2022

Nowadays automation is the key to the success. Manually handling deployments and servers is completely outdated. But why are we talking about automation here. I came across many people who want to know CI/CD in detail and see it action with GitHub which completely automates process of code build and deployment process. So in this article we are going to

  1. Learn About CI/CD
  2. Create NodeJs Express App
  3. Add GitHub Action for CI
  4. Dockerize NodeJs App
  5. Finally, Build and Push Docker Image to Private Docker Repo

So, first of all, let’s understand what’s CI/CD and what is need for it.

Continuous Integration

Continuous integration (CI) is a software practice that requires frequently committing code to a shared repository. Committing code more often detects errors sooner and reduces the amount of code a developer needs to debug when finding the source of an error. This is great for developers, who can spend more time writing code and less time debugging errors or resolving merge conflicts.
When you commit code to your repository, you can continuously build and test the code to make sure that the commit doesn’t introduce errors.

Continuous Deployment

You can configure your CD workflow to run when a GitHub event occurs (e.g. when new code is pushed to the default branch of your repository), on a set schedule, manually, or when an external event occurs using the repository dispatch webhook.
So whenever developer commits code to specified branch, he don’t need to worry about building the code , executing tests and deploying the application to specified environment.
Now we know what is CI/CD, then let’s see how we can achieve same using GitHub Actions but more of practically.
Let’s create a simple NodeJs simple application
Create a directory in your system and fire npm initand initialise node app. Install express package, using npm install express.
Create Express server by adding following piece of code in index.js file in same directory.

Hit npm start and head over to browser and type url “http://localhost:3000/” and you’ll be able to see greeting from server.
For any issues, check code base from here, https://github.com/abhay-321/node-docker-ci-cd. In many of cases, we need to run tests before merging our code into public branches. To achieve same, we’ll add dummy test case in our app and Jest library as a test framework.
Add script in package.json file as “test: jest”, when you run command npm test jest will look for all files in codebase having test.js or spec.js.
We’ll add dummy test as follows

Now run tests with npm test and you’ll be able to see one successful test case passed. Now it’s time to use github action to build and test our code. To use github actions, we need to create actions to tell git what needs to be done within scope of that action.
Github actions are located under .github/workflows. Let’s add a action for CI
Create a directory .github/workflows and create a file node.js.yml as

Let’s understand yaml file to define github action.
name: Node.js CI The name of the workflow (Optional)
on: [push] Trigger for this workflow. Determines on which type of event this workflow will be triggered
branches: [development] Work flow will be triggered if push events happens on development branch.
jobs: Contains all the jobs that run in the Node.js CI workflow.
runs-on: ubuntu-latest Decides where job will run. Here it will run on fresh virtual machine hosted by GitHub.
strategy: Used to create build matrix
matrix: can be used to run tests across multiple combinations of operating systems, platforms, and languages.
steps: Contains together all the steps that run in the build job.
- uses: actions/checkout@v2 The uses keyword specifies that this step will run v2 of the actions/checkout action. This predefined action checks out your code to runner to build and run test etc.
- name: Step name that will appear on GitHub UI
- uses: actions/setup-node@v2 Action to install the specified version of the Node.js given in node-version
- run: npm ci
The run keyword tells the job to execute a command on the runner. Same for next two commands to build and test code.
So Above workflow simply tells git that whenever code is committed to development branch, checkout that code build it and run tests.
This ensures code stability before merging code into stable branches.
You’ll be able to see workflow status under Repository -> Actions

But what about continuous development. Let’s do that as well

Continuous Deployment

Whenever code is tested and build, we can create a docker image and push that image to docker repository (Either ECR repository or Docker Repo) can be used to create a writable container layer over the specified image.
To do that let’s add one more step in our workflow.
Before that let’s dockerize our nodejs app. For same add Dockerfile in your code base at root level as in following github repo. https://github.com/abhay-321/node-docker-ci-cd/blob/development/Dockerfile

Adding this you can test your docker image locally as
docker build -t ci-cd-app:latest. Once your image is built, you can run docker run -p 3000:3000 ci-cd-app:latest. You can add -d flag to run container in detached mode. To know more about dockerizing node app, please visit this article.

Now we have added Dockerfile, let’s add one more step in work flow to build and push our docker image to docker hub.
Add following code snippet at end of your workflow yaml file

Here we’re adding predefined action which is used to build and push docker image.
image: Name of private repository in docker hub.
registry: Type of docker registry used to store docker image.
username: Docker username stored under Settings -> Secrets in Github Repo
password: Docker password stored under Settings -> Secrets in Github Repo
dockerfile: Dockerfile used to build docker image with specified commands

You can either push your image to Docker Hub or AWS ECR, in our example we’re pushing image into docker hub repository. Once you commit changes to development, work flow will be triggered and once it’s succeeded, you’ll be able to image in docker hub as follows. You can share it with anyone.

That image can be used to run a container over ECS or GKE to deploy your application.
That’s it, we have built a complete CI/CD workflow using github actions here.
Though, it’s very simple and basic flow, Github actions can be used based on environments, deployments, security, Automation like automating issue assigning process or greeting user.
You can checkout complete code base here https://github.com/abhay-321/node-docker-ci-cd.
Thanks for reading, In case of any doubts feel free to ask them in comment section, I’ll be happy to help 🙂

--

--

Abhay Ahire

Full stack Dev with Angular, Java , Node and Devops Engg AWS