M$ newest purchase got you down? Try Gitlab instead, you can’t argue with free everything and a solid interface to boot. One of my favorite things about it are the runners. Not only are the free of charge, but they are extremely useful and fairly easy to setup.
For this post I will be sharing code samples and configs for executing a deployment from a docker container inside a Gitlab shared runner. The target production server is an Ubuntu 16.04 Digital Ocean droplet.
Digital Ocean Steps
- Spin up and setup a droplet of whatever size you’d like.
- After completing initial setup, as your non root user, generate SSH keys on the remote machine with
ssh-keygenmaking sure to provide no password.
- Add the newly created public key to the authorized keys with this command
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys.
- At this point, you must have node installed to run
npm i -g pm2which we will use for our daemon.
- Next remove or comment out the lines directly below this comment in your .bashrc
#If not running interactively don't do anythingthis allows us to source our profile later on.
cat ~/.ssh/id_rsaand copy the output to clipboard, but keep in mind this is a private key and should be concealed.
- Assuming you’ve already created a repository for your project navigate to settings > ci/cd > variables.
- Add three variables
$SSH_PRIVATE_KEYwhere the values reflect the keys.
- Copy the following code into your project root with the filename
.gitlab-ci.ymlthis where the magic happens.
However magical it may be, this will always fail on first deploy because pm2 hasn’t been started yet. So we need to do that back on our droplet after it’s failed. Probably something along the lines of
cd ~/yourprojectdir && pm2 start index.js should do it. Now when we retry the deployment all should be Gucci.
You may be wondering why we don’t just use pm2’s watch feature, and it’s a good question. As per their docs..
Watching system does not provide any graceful action, pm2 kills and restarts your application without sending SIGINT
Our solution, when ran in a cluster, takes down each instance one at a time, meaning zero downtime.