Prerequisites
- Virtual Machine with Public IP
- Docker, Docker Compose installed
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:
Create a directory that contains the docker-compose file. Save it as DIRECTORY variable.
Step 2: Create Repository 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
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.
Top comments (0)