5 min read

How I setup CI/CD Workflow with Github Actions , EC2 Instances and Docker for Golang Fiber

How I setup CI/CD Workflow with Github Actions , EC2 Instances and Docker for Golang Fiber

What is CI/CD ?

CI/CD (Continuous Integration and Continuous Delivery) and Docker serve different purposes but complement each other well in modern software development practices. Here's why we need both CI/CD and Docker:

  1. Continuous Integration (CI): CI is a development practice that involves regularly merging code changes from multiple developers into a shared repository. CI helps identify issues early by automatically building and testing the codebase upon each commit. It ensures that changes are integrated smoothly and helps maintain code quality. CI allows developers to catch and fix bugs quickly, reducing the time and effort required for manual testing.
  2. Continuous Delivery (CD): CD extends CI by automating the deployment of software to production or staging environments. It ensures that the software is always in a deployable state and ready for release. CD pipelines automate the build, test, and deployment processes, reducing the risk of errors introduced during manual deployments. It enables faster and more frequent releases, leading to faster feedback loops and the ability to deliver new features and updates to users quickly.

Docker: Docker is a containerization platform that allows you to package an application along with its dependencies into a standardized container image. Docker provides isolation and reproducibility, ensuring that an application runs consistently across different environments. Containers encapsulate the entire runtime environment, including the operating system, libraries, and dependencies, making it easier to deploy and run applications consistently across different systems.

Docker also enables easy scalability and portability of applications. Containers can be deployed quickly on various platforms, including local development environments, cloud servers, and orchestration frameworks like Kubernetes. Docker images can be versioned and shared, making it easier to distribute and collaborate on software projects.

By combining CI/CD and Docker, you can achieve the following benefits:

  • Automated and consistent build, test, and deployment processes.
  • Faster feedback loops, allowing for rapid iteration and bug fixing.
  • Improved code quality through automated testing and integration.
  • Reduced time and effort spent on manual deployments.
  • Greater scalability and portability of applications.
  • Simplified environment setup and management for development and production.
  • Enables practices like immutable infrastructure and infrastructure as code.

Overall, CI/CD and Docker work hand in hand to improve the software development lifecycle by streamlining the process, reducing errors, and enabling more efficient delivery of software.

Prerequisites

  1. An AWS account and ec2 instance with docker installed
  2. Basic knowledge how to setup secret key . Click here
  3. Docker Hub account . Click here

Step 1: Setting up your GitHub repository

  1. Create a new repository on GitHub or use an existing one.
  2. Initialize it with a .gitignore file suitable for Golang projects.
  3. Clone the repository to your local development environment.

Step 2: Create a Dockerfile

In the root of your project, create a file called Dockerfile.

Add the following content to the Dockerfile:

# Use the official Golang image as the base image
FROM golang:1.17-alpine AS builder

# Set the working directory inside the container
WORKDIR /app

# Copy only the necessary Go module files to enable caching
COPY go.mod go.sum ./

# Download and cache the Go module dependencies
RUN go mod download

# Copy the source code into the container
COPY . .

# Build the Go application
RUN go build -o main

# Use a minimal base image for the final runtime container
FROM alpine:latest

# Copy the compiled binary from the builder stage
COPY --from=builder /app/main /app/main

# Expose the port the application will run on
EXPOSE 3000

# Set the command to run the binary executable of your Go application
CMD ["/app/main"]

Step 3: Configure GitHub Actions secret and variables

  1. Go to your GitHub repository.
  2. Click on the "Settings" tab.
  3. In the left sidebar, click on "Secrets".
  4. Click on "New repository secret".
  5. Enter a name for the secret, such as "DOCKERHUB_USERNAME".
  6. Enter the value of your Docker Hub username in the "Value" field.
  7. Click on "Add secret" to save it.
  8. Same goes to password . Enter a name for the secret, such as "DOCKERHUB_PASSWORD" .
  9. Repeat step 6 and 7 .

Step 4: Configure GitHub Actions

Inside your repository, navigate to the "Actions" tab.

Choose a workflow template or create a new one.

Replace the template with the following content: Replace your-dockerhub-username/repository-name with your Docker Hub username and the desired repository name.

name: CI/CD

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Go
        uses: actions/setup-go@v2
        with:
          go-version: 1.17

      - name: Build and Test
        run: |
          go build -v ./...
          go test -v ./...

      - name: Log in to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_PASSWORD }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v2
        with:
          context: .
          push: true
          tags: your-dockerhub-username/repository-name

  restart-docker:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Restart Docker on EC2
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          password: ${{ secrets.EC2_PASSWORD }}
          script: |
            sudo systemctl restart docker
            docker pull your-dockerhub-username/repository-name
            docker run -d -p 3000:3000 your-dockerhub-username/repositoryname

Step 5: Prepare Amazon EC2 Instance

  1. Launch an Amazon EC2 instance (Linux-based) and ensure it is running.
  2. Install Docker on the EC2 instance by following the official Docker installation instructions for your Linux distribution.

Step 6: Deploying the Docker image

SSH into your EC2 instance using the appropriate credentials and IP address.

Pull the Docker image from Docker Hub:

docker pull your-dockerhub-username/repository-name

Run the Docker container:The p option maps the container's port 3000 to the EC2 instance's port 3000.

docker run -d -p 3000:3000 your-dockerhub-username/repository-name

Now, whenever you push changes to your repository's main branch, GitHub Actions will automatically build, test, and push a new Docker image. The EC2 instance will then pull the latest image and run it, ensuring your Golang Fiber application is up to date and deployed.

How it was going ?


Final Words

I believe that's all there is to setting up CI/CD for someone like me, a beginner. There are many advanced methods available, such as using Docker Compose, configuring SSH with private keys, implementing Kubernetes, and more. However, the choice depends on your project and design. In my case, this is just a pet project. Instead of doing nothing and wasting my time, why not work on something that allows me to enhance and improve my skills .