Implementing Modern CI/CD Pipelines with GitHub Actions and Docker
Learn how to build a robust CI/CD pipeline using GitHub Actions and Docker, covering automated testing, building, and deployment to Docker Hub and cloud servers.

Is your company ready for AI? Download our free checklist →
Download checklistIntroduction
In today’s fast‑paced software development world, continuous integration and continuous delivery (CI/CD) are no longer optional—they are essential. Modern CI/CD pipelines automate code testing, building, and deployment, ensuring that every change is validated and delivered quickly and reliably. Two of the most popular tools for building such pipelines are GitHub Actions and Docker. GitHub Actions provides a powerful, integrated automation platform, while Docker ensures consistent environments across development, testing, and production. In this post, we’ll walk through creating a production-grade CI/CD pipeline that builds a Docker image, pushes it to Docker Hub, and deploys it to a remote server—all triggered by a git push to the main branch.
Why GitHub Actions and Docker?
- GitHub Actions is tightly integrated with GitHub repositories, offering hundreds of pre‑built actions and seamless context (e.g., pull requests, branches, secrets). It is free for public repositories and has generous limits for private ones.
- Docker packages your application with its dependencies, eliminating “it works on my machine” problems. Containers are lightweight, portable, and can be run on any system that supports Docker.
- Combined, you get a pipeline that builds, tests, and ships your application with minimal manual effort, increased confidence, and faster feedback loops.
Prerequisites
Before we dive in, ensure you have the following:
- A GitHub repository with your application code (e.g., a Node.js, Python, or Go app).
- A Docker Hub account (you can create one for free).
- A remote server (e.g., a VPS) with Docker installed and SSH access.
- Basic knowledge of YAML, Docker, and Git.
Step 1: Dockerize Your Application
First, you need a Dockerfile at the root of your project. Here’s a simple example for a Node.js app:
FROM node:18-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
FROM node:18-alpine
WORKDIR /app
COPY --from=build /app ./
EXPOSE 3000
CMD ["node", "index.js"]
This multi‑stage build reduces final image size and improves security. For other languages, adjust accordingly.
Step 2: Create the GitHub Actions Workflow
In your repository, create a file at .github/workflows/deploy.yml. This workflow will be triggered on every push to the main branch.
Workflow Overview
- Checkout the code.
- Log in to Docker Hub using stored secrets.
- Build the Docker image with a unique tag (e.g.,
${{ github.sha }}). - Push the image to Docker Hub.
- Deploy to your server via SSH, pulling the new image and restarting the container.
Here is the complete workflow file:
name: Build and Deploy
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and tag Docker image
run: |
docker build -t yourusername/yourapp:${{ github.sha }} .
docker tag yourusername/yourapp:${{ github.sha }} yourusername/yourapp:latest
- name: Push Docker image to Docker Hub
run: |
docker push yourusername/yourapp:${{ github.sha }}
docker push yourusername/yourapp:latest
- name: Deploy to server
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
docker pull yourusername/yourapp:latest
docker stop yourapp || true
docker rm yourapp || true
docker run -d --name yourapp -p 80:3000 yourusername/yourapp:latest
Important: Replace yourusername/yourapp with your Docker Hub username and repository name. Also, add the following secrets to your repository (Settings → Secrets and variables → Actions):
Want a personalized diagnostic? Complete our free checklist →
Download checklistDOCKER_USERNAME: Your Docker Hub username.DOCKER_PASSWORD: Your Docker Hub password or access token.SSH_HOST: Your server’s IP address.SSH_USER: The SSH user (e.g.,rootordeploy).SSH_PRIVATE_KEY: Your SSH private key (the public key must be added to the server’s~/.ssh/authorized_keys).
Step 3: Add Automated Testing
A robust pipeline should include tests before building. Add a test job that runs before the build-and-deploy job. For example, for a Node.js app:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
build-and-deploy:
needs: test
runs-on: ubuntu-latest
...
Now, the deployment will only proceed if all tests pass.
Step 4: Optimizing the Pipeline
Caching Dependencies
Caching can significantly speed up your pipeline. Use the actions/cache action to cache Docker layers or npm packages. For Docker, you can also use Docker’s buildx with caching to remote storage.
Using Docker Compose
If your application uses multiple services (e.g., a web server and a database), you can define a docker-compose.yml and use it in your deployment script. This simplifies running multi‑container applications.
Versioning Tags
Instead of always using latest, consider using semantic versioning or Git tags. You can push tags to trigger builds that produce versioned images.
Step 5: Monitoring and Rollbacks
Once deployed, monitor your application. Tools like UptimeRobot, Sentry, or New Relic can alert you to issues. For rollbacks, you can push a previous Docker tag or revert the Git commit.
Additional Resources
- GitHub Actions documentation – official guide on creating workflows.
- Docker’s best practices – tips for writing efficient Dockerfiles.
Conclusion
By combining GitHub Actions and Docker, you have created a powerful, automated CI/CD pipeline that ensures your application is consistently built, tested, and deployed. This setup reduces manual errors, accelerates release cycles, and frees your team to focus on writing great code. Start small, iterate, and expand your pipeline as your project grows. Happy coding!
Ready for the next step? Evaluate your company with our free checklist →
Download checklistRelated posts
- Backend▣
Ada Lovelace: The Victorian Visionary Who Wrote the First Algorithm in 1843
Ada Lovelace: The Victorian Visionary Who Wrote the First Algorithm in 1843
Sep 29, 2026
- AI & ML◈
Apple Unveils 2026 AI Developer Tools: A New Era for On-Device Intelligence
Apple Unveils 2026 AI Developer Tools: A New Era for On-Device Intelligence
Sep 28, 2026
- AI & ML◈
The 7% Problem: Why Companies Are Bleeding Money on AI While Ignoring Their People
The 7% Problem: Why Companies Are Bleeding Money on AI While Ignoring Their People
Sep 27, 2026