DEV Community

Cover image for Basic CICD with GitHub Action
Raymond
Raymond

Posted on

Basic CICD with GitHub Action

Prerequisites

  • Virtual Machine with Public IP
  • Docker, Docker Compose installed

Diagram

Diagram

When the developer pushes a commit to the repository, GitHub Action (GA) triggers the pipeline that builds the docker image and pushes it to GitHub Container Registry (ghcr.io). Then, the next job is to connect to the server by SSH, pull the latest Docker image, and restart Docker Compose.

Walkthrough

Step 1: Create a docker-compose file

services:
  web:
    image: ghcr.io/yourusername/your-web-app:latest
    ports:
      - "8080:8080"
    environment:
      - DATABASE_HOST=db
      - DATABASE_PORT=5432
    depends_on:
      - db
  db:
    image: ghcr.io/yourusername/your-database:latest
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=mydatabase
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypassword
    volumes:
      - db-data:/var/lib/postgresql/data
volumes:
  db-data:
Enter fullscreen mode Exit fullscreen mode

Create a directory that contains the docker-compose file. Save it as DIRECTORY variable.

Step 2: Create Repository Secrets

GitHub Secrets

Go to Settings → Secrets and variables → Repository secrets → New repository secret.

Step 3: Create a Github Workflow

Create .github/workflows/deploy.yaml file

name: Deploy to VPS
on:
  push:
    branches:
      - main
jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Set SHA-COMMIT
        id: vars
        run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
      - name: Build and push image
        uses: docker/build-push-action@v5
        with:
          context: . 
          platforms: linux/amd64
          push: true
          tags: |
            ghcr.io/yourusername/your-web-app:latest
            ghcr.io/yourusername/your-web-app:${{ steps.vars.outputs.sha_short }
  deploy:
    needs: build
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Deploy
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.KEY }}
          port: ${{ secrets.PORT }}
          command_timeout: 30m
          script: |
            cd ${{ vars.DIRECTORY }}
            docker compose pull
            docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Note: Build and push image job contains context. If you include multiple projects in 1 repository, please specify the correct context

Follow my repository here:

https://github.com/tinhtq/devops-exercise.git

Step 4: Test it

Push a commit to this repository and see the result.

Test Result

Top comments (0)