Implementing CI/CD with
GitHub Actions & Docker
Continuous Integration and Continuous Deployment (CI/CD) are essential
practices in modern software development, enabling teams to deliver reliable
and scalable applications quickly. GitHub Actions provides a powerful,
integrated solution for automating workflows directly within your GitHub
repositories, while Docker ensures consistent and reproducible environments.
How to implement a CI/CD pipeline using GitHub Actions and Docker. We’ll
cover the basics, create a Dockerized application, and configure GitHub Actions
to automate builds, tests, and deployments.
CI/CD, GitHub Actions &Docker
What is CI/CD:
Continuous Integration (CI): Automates building and testing your code after
every commit to catch issues early.
Continuous Deployment (CD): Automatically deploys tested code changes to
production, ensuring faster delivery cycles.
What is GitHub Actions:
GitHub Actions is a CI/CD platform integrated into GitHub, enabling you to
define workflows in YAML files. Key features include:
Event-driven automation (e.g., triggered by push or pull_request events).
Support for reusable workflows.
Integration with Docker and other third-party tools.
The Role of Docker:
Docker enables the creation of isolated and reproducible application
environments through containerization. By defining your application’s
environment in a Dockerfile, you ensure that it behaves consistently across
local and production systems.
Setting Up GitHub Actions for CI/CD
Repository Setup
Start by creating or cloning a GitHub repository.
Initialize the repository with your application’s codebase.
Creating a GitHub Actions Workflow File
Inside your repository, create a folder .github/workflows.
Add a file named ci-cd.yml.
Example workflow definition:
name: CI/CD Pipeline
on:
push:
branches:
- main
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '16'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
This example workflow checks out the code, installs dependencies, and runs
tests whenever changes are pushed to the main branch.
Creating a Dockerized Application
Writing a Dockerfile
Create a Dockerfile in the root directory to containerize your application.
Example Dockerfile:
# Use Node.js as the base image
FROM node:16
# Set the working directory inside the container
WORKDIR /app
# Copy package files and install dependencies
COPY package*.json ./
RUN npm install
# Copy the rest of the application code
COPY . .
# Expose the application port
EXPOSE 3000
# Define the default command
CMD ["npm", "start"]
Testing the Docker Image Locally
Build the Docker image:
docker build -t my-app .
Run the Docker container:
docker run -p 3000:3000 my-app
Integrating Docker with GitHub Actions
Extending the Workflow File for Docker
Modify the ci-cd.yml to build and test the Docker image:
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Build Docker image
run: docker build -t my-app .
- name: Run container tests
run: docker run my-app npm test
Pushing the Docker Image to a Registry
Add steps to push the image to Docker Hub:
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Push Docker image
run: |
docker tag my-app my-dockerhub-username/my-app:latest
docker push my-dockerhub-username/my-app:latest
Replace my-dockerhub-username with your Docker Hub username.
Deploying the Application
To deploy the Dockerized application, you can:
Use Docker Compose for local setups.
Deploy to a cloud platform like Kubernetes, AWS ECS, or Azure Container
Instances.
For a simple deployment on a Docker host:
Pull the Docker image:
docker pull my-dockerhub-username/my-app:latest
Run the Container
docker run -d -p 80:3000 my-dockerhub-username/my-app:latest
Benefits of Using GitHub Actions and Docker Together:
Streamlined Automation: GitHub Actions automates testing and deployment,
saving time.
Reproducibility: Docker ensures the same environment across local and
production systems.
Scalability: Supports seamless scaling for modern cloud-native applications.