| title | Automate your builds with GitHub Actions | ||
|---|---|---|---|
| linkTitle | Automate your builds with GitHub Actions | ||
| weight | 50 | ||
| keywords | CI/CD, GitHub Actions, Node.js, Docker | ||
| description | Learn how to configure CI/CD using GitHub Actions for your Node.js application. | ||
| aliases |
|
Complete all the previous sections of this guide, starting with Containerize a Node.js application.
You must also have:
- A GitHub account.
- A Docker Hub account.
In this section, you'll set up a CI/CD pipeline using GitHub Actions to automatically:
- Build your Node.js application inside a Docker container.
- Run unit and integration tests, and make sure your application meets solid code quality standards.
- Perform security scanning and vulnerability assessment.
- Push production-ready images to Docker Hub.
To enable GitHub Actions to build and push Docker images, you'll securely store your Docker Hub credentials in your new GitHub repository.
-
Create a Personal Access Token (PAT) from Docker Hub.
- From your Docker Hub account, go to Account Settings → Security.
- Generate a new Access Token with Read/Write permissions.
- Name it something like
docker-nodejs-sample. - Copy and save the token — you'll need it in Step 4.
-
Create a repository in Docker Hub.
- From your Docker Hub account, select Create a repository.
- For the Repository Name, use something descriptive — for example:
nodejs-sample. - Once created, copy and save the repository name — you'll need it in Step 4.
-
Create a new GitHub repository for your Node.js project.
-
Add Docker Hub credentials as GitHub repository secrets.
In your newly created GitHub repository:
-
From Settings, go to Secrets and variables → Actions → New repository secret.
-
Add the following secrets:
Name Value DOCKER_USERNAMEYour Docker Hub username DOCKERHUB_TOKENYour Docker Hub access token (created in Step 1) DOCKERHUB_PROJECT_NAMEYour Docker Project Name (created in Step 2) These secrets let GitHub Actions to authenticate securely with Docker Hub during automated workflows.
-
-
Connect your local project to GitHub.
Link your local project
docker-nodejs-sampleto the GitHub repository you just created by running the following command from your project root:$ git remote set-url origin https://github.com/{your-username}/{your-repository-name}.git[!IMPORTANT] Replace
{your-username}and{your-repository}with your actual GitHub username and repository name.To confirm that your local project is correctly connected to the remote GitHub repository, run:
$ git remote -vYou should see output similar to:
origin https://github.com/{your-username}/{your-repository-name}.git (fetch) origin https://github.com/{your-username}/{your-repository-name}.git (push)
This confirms that your local repository is properly linked and ready to push your source code to GitHub.
-
Push your source code to GitHub.
Follow these steps to commit and push your local project to your GitHub repository:
-
Stage all files for commit.
$ git add -AThis command stages all changes — including new, modified, and deleted files — preparing them for commit.
-
Commit your changes.
$ git commit -m "Initial commit with CI/CD pipeline"This command creates a commit that snapshots the staged changes with a descriptive message.
-
Push the code to the
mainbranch.$ git push -u origin mainThis command pushes your local commits to the
mainbranch of the remote GitHub repository and sets the upstream branch.
-
Once completed, your code will be available on GitHub, and any GitHub Actions workflow you've configured will run automatically.
Note
Learn more about the Git commands used in this step:
- Git add – Stage changes (new, modified, deleted) for commit
- Git commit – Save a snapshot of your staged changes
- Git push – Upload local commits to your GitHub repository
- Git remote – View and manage remote repository URLs
Now you'll create a GitHub Actions workflow that builds your Docker image, runs tests, and pushes the image to Docker Hub.
-
From your repository on GitHub, select the Actions tab in the top menu.
-
When prompted, select Set up a workflow yourself.
This opens an inline editor to create a new workflow file. By default, it will be saved to:
.github/workflows/main.yml -
Add the following workflow configuration to the new file:
name: CI/CD – Node.js Application with Docker
on:
push:
branches: [main]
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
jobs:
test:
name: Run Node.js Tests
runs-on: ubuntu-latest
services:
postgres:
image: postgres:18-alpine
env:
POSTGRES_DB: todoapp_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Cache npm dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: ${{ runner.os }}-npm-
- name: Build test image
uses: docker/build-push-action@v6
with:
context: .
target: test
tags: nodejs-app-test:latest
platforms: linux/amd64
load: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
- name: Run tests inside container
run: |
docker run --rm \
--network host \
-e NODE_ENV=test \
-e POSTGRES_HOST=localhost \
-e POSTGRES_PORT=5432 \
-e POSTGRES_DB=todoapp_test \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
nodejs-app-test:latest
env:
CI: true
timeout-minutes: 10
build-and-push:
name: Build and Push Docker Image
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Cache Docker layers
uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: ${{ runner.os }}-buildx-
- name: Extract metadata
id: meta
run: |
echo "REPO_NAME=${GITHUB_REPOSITORY##*/}" >> "$GITHUB_OUTPUT"
echo "SHORT_SHA=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push multi-arch production image
uses: docker/build-push-action@v6
with:
context: .
target: production
push: true
platforms: linux/amd64,linux/arm64
tags: |
${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKERHUB_PROJECT_NAME }}:latest
${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKERHUB_PROJECT_NAME }}:${{ steps.meta.outputs.SHORT_SHA }}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache,mode=maxThis workflow performs the following tasks for your Node.js application:
- Triggers on every
pushorpull requestto themainbranch. - Builds a test Docker image using the
teststage. - Runs tests in a containerized environment.
- Stops the workflow if any test fails.
- Caches Docker build layers and npm dependencies for faster runs.
- Authenticates with Docker Hub using GitHub secrets.
- Builds an image using the
productionstage. - Tags and pushes the image to Docker Hub with
latestand short SHA tags.
Note
For more information about docker/build-push-action, refer to the GitHub Action README.
After adding your workflow file, trigger the CI/CD process.
-
Commit and push your workflow file
From the GitHub editor, select Commit changes….
- This push automatically triggers the GitHub Actions pipeline.
-
Monitor the workflow execution
- From your GitHub repository, go to the Actions tab.
- Select the workflow run to follow each step: test, build, security, and (if successful) push and deploy.
-
Verify the Docker image on Docker Hub
- After a successful workflow run, visit your Docker Hub repositories.
- You should see a new image under your repository with:
- Repository name:
${your-repository-name} - Tags include:
latest– represents the most recent successful build; ideal for quick testing or deployment.<short-sha>– a unique identifier based on the commit hash, useful for version tracking, rollbacks, and traceability.
- Repository name:
[!TIP] Protect your main branch To maintain code quality and prevent accidental direct pushes, enable branch protection rules:
- From your GitHub repository, go to Settings → Branches.
- Under Branch protection rules, select Add rule.
- Specify
mainas the branch name.- Enable options like:
- Require a pull request before merging.
- Require status checks to pass before merging.
This ensures that only tested and reviewed code is merged into
mainbranch.
In this section, you set up a comprehensive CI/CD pipeline for your containerized Node.js application using GitHub Actions.
What you accomplished:
- Created a new GitHub repository specifically for your project.
- Generated a Docker Hub access token and added it as a GitHub secret.
- Created a GitHub Actions workflow that:
- Builds your application in a Docker container.
- Run tests in a containerized environment.
- Pushes an image to Docker Hub if tests pass.
- Verified the workflow runs successfully.
Your Node.js application now has automated testing and deployment.
Deepen your understanding of automation and best practices for containerized apps:
- Introduction to GitHub Actions – Learn how GitHub Actions automate your workflows
- Docker Build GitHub Actions – Set up container builds with GitHub Actions
- Workflow syntax for GitHub Actions – Full reference for writing GitHub workflows
- GitHub Container Registry – Learn about GHCR features and usage
- Best practices for writing Dockerfiles – Optimize your image for performance and security
Next, learn how you can deploy your containerized Node.js application to Kubernetes with production-ready configuration. This helps you ensure your application behaves as expected in a production-like environment, reducing surprises during deployment.