Streamlining CI/CD Pipelines: Automating Docker and Kubernetes Deployment with GitHub Actions

As I continue building my skills in DevOps, I recently explored automating a CI/CD workflow using AWS EKS. The process involves building and pushing a Docker image to Docker Hub and deploying it to an AWS Elastic Kubernetes Service (EKS) cluster using GitHub Actions. Here’s a simplified breakdown of the steps I followed:
Workflow File: Overview
This GitHub Actions workflow has two main jobs:
- Build and Push Docker Image: Builds a Docker image and pushes it to Docker Hub.
- Deploy to Kubernetes: Deploys the Docker image to a Kubernetes cluster using Kubernetes manifests.
Detailed Explanation of Each Step
Workflow Title
name: Docker CI/CD with Kubernetes Deployment
The workflow title clearly defines its purpose—automating the process of building, pushing, and deploying Docker images to a production environment using Kubernetes and GitHub Actions.
Trigger
on:
push:
branches:
- main
This section triggers the workflow every time a commit is pushed to the main branch. It ensures your CI/CD pipeline runs whenever new changes are made to the production-ready code.
Job 1: Build and Push Docker Image
Step 1: Checkout Code
- name: Checkout code
uses: actions/checkout@v4
This pulls the latest version of your repository code into the GitHub Actions runner. It’s the first step in the pipeline, ensuring that the code being built and deployed is the latest version.
Step 2: Log in to Docker Hub
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- Purpose: Authenticates the runner with Docker Hub.
- How It Works: The credentials (username and password) are securely stored as GitHub Secrets and passed to the action at runtime.
- Why Needed: This step allows the pipeline to push the built Docker image to your Docker Hub repository.
Step 3: Build Docker Image
- name: Build Docker image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/my-app:latest .
- Purpose: Builds the Docker image of your application.
- Details:docker build generates an image using your Dockerfile.The -t flag tags the image with the name <DockerHubUsername>/my-app:latest.
- Why Needed: Converts your application into a portable containerized image.
Step 4: Push Docker Image
- name: Push Docker image
run: |
docker push ${{ secrets.DOCKER_USERNAME }}/my-app:latest
- Purpose: Uploads the Docker image to Docker Hub.
- Details: The image is now publicly or privately available in your Docker Hub repository.
- Why Needed: Ensures the image can be pulled later for deployment in the Kubernetes cluster.
Job 2: Deploy to AWS EKS
Step 1: Configure AWS Credentials
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2
- Purpose: Authenticates with AWS using an IAM user’s access key and secret key.
- Details:Credentials are securely stored as GitHub Secrets.The region (us-west-2) is where your EKS cluster is hosted.
- Why Needed: Grants the runner access to your AWS resources, like the EKS cluster.
Step 2: Set up Kubernetes Context
- name: Set up kubectl for EKS
run: |
aws eks update-kubeconfig --region us-west-2 --name my-eks-cluster
curl -LO "https://dl.k8s.io/release/v1.31.0/bin/linux/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/
- Purpose: Configures the runner to communicate with your AWS EKS cluster.
- Details:aws eks update-kubeconfig generates the kubeconfig file for your EKS cluster.The curl command downloads the latest version of kubectl (v1.31.0).The chmod and mv commands make kubectl executable and accessible globally.
- Why Needed: Allows the runner to interact with Kubernetes resources within your EKS cluster.
Step 3: Apply Kubernetes Manifests
- name: Apply Kubernetes manifests
run: |
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
- Purpose: Deploys your application to the EKS cluster.
- Details:deployment.yaml: Defines the pod configuration, including the Docker image to use.service.yaml: Exposes your pods to the network (e.g., via LoadBalancer or NodePort).
- Why Needed: Automates the deployment process, ensuring your application is running on the cluster.
How to Create GitHub Secrets
Navigate to Secrets Settings:
- Go to your GitHub repository.
- Click on Settings > Secrets and variables > Actions
Add Secrets: Click New repository secret and add the following
- DOCKER_USERNAME: Your Docker Hub username.
- DOCKER_PASSWORD: Your Docker Hub password or access token.
- AWS_ACCESS_KEY_ID: Your AWS access key ID (from the IAM user).
- AWS_SECRET_ACCESS_KEY: Your AWS secret access key (from the IAM user).
Secure Your Secrets: Ensure you never hard-code these values in your workflow file.
Conclusion
This workflow showcases how to seamlessly integrate Docker and Kubernetes into a CI/CD pipeline using GitHub Actions. It simplifies deploying applications and ensures efficiency and consistency.
name: Docker CI/CD with Kubernetes Deployment for Production
on:
push:
branches:
- main
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
# Step 1: Checkout the Code
- name: Checkout code
uses: actions/checkout@v4
# Step 2: Log in to Docker Hub
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# Step 3: Build Docker Image
- name: Build Docker image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME }}/my-app:latest .
# Step 4: Push Docker Image
- name: Push Docker image
run: |
docker push ${{ secrets.DOCKER_USERNAME }}/my-app:latest
deploy-to-eks:
needs: build-and-push
runs-on: ubuntu-latest
steps:
# Step 1: Configure AWS Credentials
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2 # Replace with your AWS region
# Step 2: Set up kubectl for EKS
- name: Set up kubectl for EKS
run: |
aws eks update-kubeconfig --region us-west-2 --name my-eks-cluster
curl -LO "https://dl.k8s.io/release/v1.31.0/bin/linux/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/
# Step 3: Apply Kubernetes Manifests
- name: Apply Kubernetes manifests
run: |
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml