Last updated August 18, 2021.
Oddly, I still enjoy running my own Linux server. A few years ago, I became interested in deploying a container-based application using an automated Github-Actions-based CI/CD workflow to a $5/mo Linode VPS server. These workflows run the test suite against PRs and build and deploy docker images via SSH.
I recently split up this workflow into separate files and stopped using the Docker-based
sut workflow. I’ve replaced it with the native Github Ruby pipeline, which is substantially faster than building a Docker image just to run tests.
Here’s my test workflow pipeline that runs the Ruby-based test suite on every new PR.
Once PRs are merged to
main, a follow-up
Deploy workflow builds a Docker image and deploys it to my Linode server via SSH:
# in .github/workflows/deploy.yml name: Deploy on: push: branches: - main jobs: # Push image to GitHub Packages. # See also https://docs.docker.com/docker-hub/builds/ build: runs-on: ubuntu-latest if: github.event_name == 'push' steps: - uses: actions/checkout@v2 - name: Build image run: docker build . --file Dockerfile --tag docker.pkg.github.com/my-profile/my-repo/my-image:latest - name: Log into registry run: echo "$" | docker login docker.pkg.github.com -u $ --password-stdin - name: Push image run: docker push docker.pkg.github.com/my-profile/my-repo/my-image:latest deploy: needs: build runs-on: ubuntu-latest if: github.event_name == 'push' steps: - uses: actions/checkout@v2 - name: Deploy run: | echo "$" > ssh_key chmod 700 ssh_key ssh -o StrictHostKeyChecking=no -i ssh_key $@$ "sh -s" < deploy.sh rm ssh_key
The above Deploy workflow references a custom
deploy.sh script. Here’s a generic example of what that script does:
#!/bin/sh # This script runs on the docker server to deploy the application. It can be kicked off locally via: # # ``` # ssh my-server < deploy.sh # ``` set -e echo 'Removing dangling images' yes | docker image prune echo 'Pulling latest' docker pull docker.pkg.github.com/my-profile/my-repo/my-image:latest echo 'Stopping the container' docker container stop my-app || true until [ "`docker ps --filter 'name=my-app' --format ''`" == "" ]; do sleep 0.1; done; echo 'Starting the container' docker run --rm --name my-app -d -p 3000:3000 docker.pkg.github.com/my-profile/my-repo/my-image:latest startup.sh