I decided to take my previous learning of GitHub Actions a bit further to deploy my application on a bare metal Linux server i.e. Continuous Deployment.
Basically following is what I wanted to achieve:
- Build and push latest images of my application to a container repository
- Docker-compose up the latest images from my server
The first step I had already done in my previous post. For the second step, I wanted to do it manually and then automate that process later.
Following is the manual step I was doing to run the applications on my server:
- Use SCP to copy
docker-compose.yml
file into my remote server from local - SSH login into my server
- Docker login to
ghcr.io
repository where my images were pushed - Docker-compose up the copied
docker-compose.yml
file
Thanks to already built GitHub Actions available in the marketplace, I was able to automate the above manual process:
name: CD
on:
push:
branches: [ main ]
env:
REGISTRY: ghcr.io
REPO: my-repo
BE: backend
FE: frontend
ORG: my-org
QA_DC: docker-compose-qa.yml
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Log in to the Container registry
uses: docker/login-action@v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Build Backend
uses: docker/build-push-action@v2
with:
context: ./${{ env.BE }}
push: true
tags: ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.REPO }}/${{ env.BE }}:latest,${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.REPO }}/${{ env.BE }}:${{ github.run_number }}
- name: Build Frontend
uses: docker/build-push-action@v2
with:
context: ./${{ env.FE }}
push: true
tags: ${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.REPO }}/${{ env.FE }}:latest,${{ env.REGISTRY }}/${{ env.ORG }}/${{ env.REPO }}/${{ env.FE }}:${{ github.run_number }}
- name: Copy files to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.QA_HOST }}
username: ${{ secrets.QA_USERNAME }}
password: ${{ secrets.QA_PASSWORD }}
port: ${{ secrets.QA_PORT }}
timeout: 120s
rm: true
source: "${{ env.QA_DC }}"
target: "/${{ env.REPO }}"
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.QA_HOST }}
username: ${{ secrets.QA_USERNAME }}
password: ${{ secrets.QA_PASSWORD }}
port: ${{ secrets.QA_PORT }}
script: |
echo ${{ secrets.GHCR_TOKEN }} | docker login ${{ env.REGISTRY }} -u ${{ secrets.GHCR_USERNAME }} --password-stdin
cd /${{ env.REPO }}
docker-compose -f ${{ env.QA_DC }} pull ${{ env.FE }} ${{ env.BE }}
docker-compose -f ${{ env.QA_DC }} up -d --build
The file is pretty much self-explanatory. Using env
variables made the script a bit more reusable which I can just copy-paste into my another CD build. secrets
are something you would have to set manually in GitHub on organization or repository level. GitHub gives you a complete solution with Github Actions (CI/CD), Github Container Repository (ghcr.io) and Secrets Management as well.