Image created by Midjourney
In the last post we created a sudo user and updated our packages. In this post we're gonna go over how to set up Docker and GitHub Actions
You'll need a "runner" in your VPS that listens to git push-es to your repository. It's basically a webhook endpoint that GitHub pings when new changes are pushed to your repo. Every time you merge to master/main, GitHub will ping this runner and it will perform some actions that you define in a config file (pull Docker images from a registry, create containers etc). To find instructions to install a runner, go to your GitHub repo and click on the Settings tab, and then click on "Runners" under the Actions section. There should be a button to create a runner which should reveal instructions that look something like this. DON'T COPY AND PASTE THESE COMMANDS. COPY THE ONES IN YOUR GITHUB
$ mkdir actions-runner && cd actions-runner
$ curl -o actions-runner-linux-x64-2.319.1.tar.gz -L https://github.com/actions/runner/releases/download/v2.319.1/actions-runner-linux-x64-2.319.1.tar.gz
$ echo "3f6efb7488a183e291fc2c62876e14c9ee732864173734facc85a1bfb1744464 actions-runner-linux-x64-2.319.1.tar.gz" | shasum -a 256 -c
$ tar xzf ./actions-runner-linux-x64-2.319.1.tar.gz
Yours would look different, but the idea is the same. Let's go over each line and understand what's going on
$ mkdir actions-runner && cd actions-runner
Pretty simple, we're just creating a directory to keep all our runner files. We then go to this directory because that's where we'll run the next few commands
$ curl -o actions-runner-linux-x64-2.319.1.tar.gz -L https://github.com/actions/runner/releases/download/v2.319.1/actions-runner-linux-x64-2.319.1.tar.gz
This fetches a tar file from GitHub that contains the runner installer
$ echo "3f6efb7488a183e291fc2c62876e14c9ee732864173734facc85a1bfb1744464 actions-runner-linux-x64-2.319.1.tar.gz" | shasum -a 256 -c
This step is optional, but recommended. We verify the hash of this file that we just downloaded to make sure it comes from a legit source (GitHub)
$ tar xzf ./actions-runner-linux-x64-2.319.1.tar.gz
This extracts the tarball so we can run the install scripts
Now run the GitHub runner and see if everything works
# Create the runner and start the configuration experience
$ ./config.sh --url https://github.com/prithajnath/portfolio --token AB6577LXKEYPRWSW2PPCS63GZVI7M# Last step, run it!
$ ./run.sh
If everything works as expected, go ahead and the runner as a systemd service. The GitHub runner instructions don't mention this but this is really important. Systemd is how you get the operating system to handle background processes for you (You can copy these commands in this section and following sections)
$ sudo ./svc.sh install
$ sudo ./svc.sh start
You can check on the status of the runner using the status command. This is
a full fledged system service so you can use your typical systemd commands
as well
$ sudo ./svc.sh status
This is what the status logs should look like
● actions.runner.prithajnath-portfolio.self-hosted.service - GitHub Actions Runner (prithajnath-portfolio.self-hosted)
Loaded: loaded (/etc/systemd/system/actions.runner.prithajnath-portfolio.self-hosted.service; enabled; preset: enabled)
Active: active (running) since Sun 2024-12-15 23:02:29 UTC; 16h ago
Main PID: 2884587 (runsvc.sh)
Tasks: 20 (limit: 1113)
Memory: 107.4M (peak: 306.4M)
CPU: 46.581s
CGroup: /system.slice/actions.runner.prithajnath-portfolio.self-hosted.service
├─2884587 /bin/bash /home/prithaj/actions-runner/runsvc.sh
├─2884590 ./externals/node20/bin/node ./bin/RunnerService.js
└─2884597 /home/prithaj/actions-runner/bin/Runner.Listener run --startuptype service
Dec 15 23:02:31 prithaj runsvc.sh[2884590]: Current runner version: '2.321.0'
Dec 15 23:02:31 prithaj runsvc.sh[2884590]: 2024-12-15 23:02:31Z: Listening for Jobs
Dec 15 23:02:32 prithaj runsvc.sh[2884590]: 2024-12-15 23:02:32Z: Running job: build_container_image
Dec 15 23:04:15 prithaj runsvc.sh[2884590]: 2024-12-15 23:04:15Z: Job build_container_image completed with result: Succeeded
Dec 15 23:04:17 prithaj runsvc.sh[2884590]: 2024-12-15 23:04:17Z: Running job: deploy_all_services
Dec 15 23:04:34 prithaj runsvc.sh[2884590]: 2024-12-15 23:04:34Z: Job deploy_all_services completed with result: Succeeded
Dec 15 23:50:22 prithaj runsvc.sh[2884590]: 2024-12-15 23:50:22Z: Running job: build_container_image
Dec 15 23:51:58 prithaj runsvc.sh[2884590]: 2024-12-15 23:51:58Z: Job build_container_image completed with result: Succeeded
Dec 15 23:52:00 prithaj runsvc.sh[2884590]: 2024-12-15 23:52:00Z: Running job: deploy_all_services
Dec 15 23:52:19 prithaj runsvc.sh[2884590]: 2024-12-15 23:52:19Z: Job deploy_all_services completed with result: Succeeded
Now that we have a GitHub runner up and running, it's time to install Docker. Docker is a widely used containerization tool and it comes in two parts.
You can find the latest instructions to install the Docker daemon here, but I have copied and pasted the two most important snippets here
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
And then the actual installation.
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Docker lets you package your application into little containers so you can
run them anywhere (with an asterisk). Your host machine, like your
DigitalOcean droplet, Raspberry pi etc may not have all the dependencies
you need to run your app. You may say that this can simply be solved by a
requirement.txt
or a Pipefile.lock
, and you
would be mostly correct, except for when you need C libraries that some
Python packages rely on (like Pandas or Numpy).
The GitHub runner listens for pushes to your GitHub repo. Every time you push to main/master, the GitHub runner will use the Docker CLI to tell the Docker daemon to start building new Docker images, push them to a registry and deploy new containers from those images
After installing Docker, you need to add your user to the
docker
group in order to be able to run Docker commands
without using sudo
all the time. Make sure you log out and
SSH back into the droplet after running this command.
$ sudo usermod -aG docker $new_user
Remember, $new_user
is the user you set in the
last article. If
everything goes well, you should be able to run docker ps
in
the terminal and see the following output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
This confirms that the Docker daemon is running and you can use the Docker
CLI without sudo
.
This was a long one. Next up we're gonna learn how to write a Dockerfile and some YAML to trigger our Github Actions Runner