Continuously Build Node.js Docker Images Using GitHub Actions
Add CI to your Node app

The great folks from GitHub added something new to their service — GitHub Actions. As of November 11, 2019, GitHub Actions is available for everyone. It is free when used from public repositories.
You can use GitHub Actions to automate all kinds of software development tasks. You, as a developer, create a YAML workflow file. GitHub stores the file inside your repository and executes the workflow.
For editing workflow files, GitHub created a workflow editor. Instead, I prefer to use my normal editor, Visual Studio Code. I added an extension to help with editing.
I started using GitHub Actions to build Mini Video Encoder, my side project. When I commit a change, it first builds and tests the project. If successful, the action creates and pushes the Docker image to Docker Hub.
In this article, I describe how to create a GitHub Action to build, test, and push a Docker image of a Node.js project. If you are interested in the final workflow file, feel free to look at the file in my GitHub repository.
Steps to Build, Test, and Push the Docker Image
To build, test, and push the Docker image of my Node.js project, the GitHub Action has to perform the following steps:
- Check out the Mini Video Encoder repository.
- Read the current version from the VERSION file.
- Increase the version using semantic versioning.
- Write the new version number to the VERSION file.
- Build, tag, and publish the Docker image.
- Commit the VERSION file.
- Send a Slack message to notify you that the new version was published.
I will translate each step into a section in the workflow YAML file and explain it.
Define the Workflow File
Each workflow file starts with the name of the action. GitHub shows this name in the Actions overview.
The statements below line two define when to trigger the workflow. I use two types. The first starts if I push
a commit to the repository. The second lets me trigger the process at a schedule
, a specific time.
The schedule uses the same syntax as Linux cron jobs. I always struggle to remember what each part means. Lucky for me, Cronitor created a tool called crontab.guru that helps. The string '0 1 * * *'
means that I want to trigger the action every night at 01:00.
1. Check out the Mini Video Encoder repository
The first step in the workflow is to check out the Mini Video Encoder repository on to the machine that executes the action.
You have to define on which platform you want the action to run using the runs-on
tag. I use Ubuntu. If you need another platform, they are available. You can also use Windows Server or Mac OS.
Below steps:
, you have to define all the stages of your workflow. The first step is the action/checkout@master
that downloads the master branch. Almost always, the first step in an Action is to check out the repository.
2. Read the current version from the VERSION file
I use a file called VERSION
to store the version of the project. During the second step, I read the version from this file.
Christian Draeger created a great GitHub Action that I use. The Action christian-draeger/read-properties
reads the value of a key-value pair that is defined in the VERSION
file.
The version then is available in the variable steps.read_property.outputs.value
. On the last line, I print the variable so that it is visible in the build log.
3. Increase the version using semantic versioning
I want to automatically increase the version when I push a change to the repository. The version number should be increased according to the semantic version scheme.
Luckily for me, Christian Draeger created another excellent action called christian-draeger/increment-semantic-version
, which updates a version number according to the semantic version rules.
On line 5, I assign the current-version
to the variable steps.read_property.output.value
. Remember that during the previous step, it read and stored the version number in the steps.read_property.output.value
variable.
With version-fragment
on line 6, you indicate to the Action which part of the version number you want to update. I use 'bug'
to increase the PATCH of the version number. See the documentation of the Action for other options.
4. Write the new version number to the VERSION file
I use the write-properties
action to store the updated version number in the VERSION
file.
I could not get the write-properties
Action to update the version number in the file. Instead, I first remove the VERSION
file and replace it with a new file that contains the new version number.
5. Build, tag, and publish a new Docker image
The WorkflowEngine
folder in the repository contains the Dockerfile
for building the Docker image of the workflow engine.
Lars Elgohr created the action elgohr/Publish-Docker-Github-Action
that builds, tags, and publishes a Docker image to Docker Hub.
You have to provide the Action with the name of the Docker Hub repository, pkalkman/mve-workflowengine
. On line 9, I use the variable with the updated version number to tag the Docker image.
To be able to upload your image to Docker Hub, you have to provide your credentials to the action using the username and password fields.
If you need to use sensitive information, you have to use GitHub Secrets. GitHub Secrets are specific to a repository. They can be created via the Settings and Secrets tabs.
After they are created you can use them in the workflow definition file.

6. Commit the VERSION file
The version number was updated and saved in the VERSION
file in steps 3 and 4. We still have to commit and push this change to the repository.
Matheus Albino created an action that commits and pushes your changes. You have to specify a github-token
so that the action can interact with the repository. I again use a secret.
The message
field allows you to set the commit message. I use the updated version number in the message. For more options such as specifying the user that performed the commit, see the documentation of the Action.
7. Send a Slack message to notify that the new version was published
The last step of the workflow file sends a message to a Slack channel to notify that a new version is available.
I use the action rtCamp/[email protected]
. RtCamp created this Action which sends a message on Slack.
You have to create a Slack webhook to allow the Action to use your Slack channel. You have to set it in the SLACK_WEBHOOK
field. I use a secret for this.
If the action completes successfully, it generates the following message in a Slack channel.

Conclusion and the Power of Open-Source
I like GitHub Actions very much. I find it very easy to combine existing Actions to create a complex workflow. At the time of writing, there are already 2118 Actions in the marketplace.
If you want to see the complete workflow, I invite you to take a look at the file in my GitHub repository.
I want to thank Christian Draeger, Matheus Albino, Lars Elgohr, Jesse Talavera-Greenberg, and rtCamp for providing all the excellent Actions that I use in my workflow.
Thank you for reading. Let me know if you already use or are planning to use GitHub Actions. I am interested. Also, if you have any questions or remarks about the article, feel free to leave a response.