I once thought about automating the deployment of my project. gitlab.com kindly provides all the tools for this, so I decided to take advantage of it by figuring out and writing a small deployment script. In this article, I share my experience with the community.
TL;DR
- Configure VPS: disable root, password login, install dockerd, configure ufw
- Generate certificates for the server and client Enable dockerd management through TCP socket: remove the -H fd:// option from the Docker config.
- ΠΡΠΎΠΏΠΈΡΠ°ΡΡ ΠΏΡΡΠΈ Π΄ΠΎ ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΠ² Π² docker.json
- Add the contents of the certificates to the GitLab CI/CD settings as variables. Write a .gitlab-ci.yml script for deployment.
I will demonstrate all examples using the Debian distribution.
Initial VPS Setup
So you've purchased an instance on , the first thing you need to do is secure your server from the aggressive outside world. I won't argue or assert anything, just look at the log /var/log/messages of my virtual server:
Screenshot
First, let's install the ufw firewall:
apt-get update && apt-get install ufwLet's set the default policy: block all incoming connections, allow all outgoing connections:
ufw default deny incoming
ufw default allow outgoingImportant: don't forget to allow SSH connections:
ufw allow OpenSSHThe general syntax is: Allow connection on port: ufw allow 12345, where 12345 is the port number or the service name. Deny: ufw deny 12345
Enable the firewall:
ufw enableLog out of the session and log back in via SSH.
Add a user, assign a password, and add them to the sudo group.
apt-get install sudo
adduser scoty
usermod -aG sudo scotyNext, we need to disable password login. To do this, copy your SSH key to the server:
ssh-copy-id root@10.101.10.28The IP of the server should be yours. Now try logging in with the previously created user, you no longer need to enter a password. Next, in the configuration settings, change the following:
sudo nano /etc/ssh/sshd_configdisable password login:
PasswordAuthentication noRestart the sshd daemon:
sudo systemctl reload sshdNow, if you or anyone else tries to enter with the root user, nothing will happen.
Next, install dockerd; I won't describe the process here, as everything may already have changed; go to the official website and follow the Docker installation steps for your virtual machine:
Certificate Generation
To manage the Docker daemon remotely, an encrypted TLS connection is required. You need to have a certificate and key, which must be generated and transferred to your remote machine. Follow the steps provided in the instructions on the official Docker website: All generated *.pem files for the server, namely ca.pem, server.pem, key.pem, should be placed in the directory /etc/docker on the server.
Configuring dockerd
In the Docker daemon startup script, remove the -H df:// option, which specifies on which host you can manage the Docker daemon.
# At /lib/systemd/system/docker.service
[Service]
Type=notify
ExecStart=/usr/bin/dockerdNext, create a configuration file if it does not exist and specify the options:
/etc/docker/docker.json
{
"hosts": [
"unix://var/run/docker.sock",
"tcp://0.0.0.0:2376"
],
"labels": [
"is-our-remote-engine=true"
],
"tls": true,
"tlscacert": "/etc/docker/ca.pem",
"tlscert": "/etc/docker/server.pem",
"tlskey": "/etc/docker/key.pem",
"tlsverify": true
}Allow connections on port 2376:
sudo ufw allow 2376Restart dockerd with the new settings:
sudo systemctl daemon-reload && sudo systemctl restart dockerLet's check:
sudo systemctl status dockerIf everything is "green", then we can assume that we have successfully configured Docker on the server.
Setting up continuous delivery on GitLab
For the GitLab worker to execute commands on the remote Docker host, you need to determine how and where to store the certificates and key for an encrypted connection to dockerd. I solved this issue by simply defining variables in the GitLab settings:
Spoiler Title
Just output the contents of the certificates and key using cat: cat ca.pem. Copy and paste into the values of the variables.
Let's write a script for deployment via GitLab. We will use the Docker-in-Docker (dind) image.
.gitlab-ci.yml
image:
name: docker/compose:1.23.2
# rewrite entrypoint to work in dind
entrypoint: ["/bin/sh", "-c"]
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
services:
- docker:dind
stages:
- deploy
deploy:
stage: deploy
script:
- bin/deploy.sh # deployment script here
Contents of the deployment script with comments:
bin/deploy.sh
#!/usr/bin/env sh
# ΠΠ°Π΄Π°Π΅ΠΌ ΡΡΠ°Π·Ρ, Π΅ΡΠ»ΠΈ Π²ΠΎΠ·Π½ΠΈΠΊΠ»ΠΈ ΠΊΠ°ΠΊΠΈΠ΅-ΡΠΎ ΠΎΡΠΈΠ±ΠΊΠΈ
set -e
# ΠΡΠ²ΠΎΠ΄ΠΈΠΌ, ΡΠΎ , ΡΡΠΎ Π΄Π΅Π»Π°Π΅ΠΌ
set -v
#
DOCKER_COMPOSE_FILE=docker-compose.yml
# ΠΡΠ΄Π° Π΄Π΅ΠΏΠ»ΠΎΠΈΠΌ
DEPLOY_HOST=185.241.52.28
# ΠΡΡΡ Π΄Π»Ρ ΡΠ΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠΎΠ² ΠΊΠ»ΠΈΠ΅Π½ΡΠ°, ΡΠΎ Π΅ΡΡΡ Π² Π½Π°ΡΠ΅ΠΌ ΡΠ»ΡΡΠ°Π΅ - gitlab-Π²ΠΎΡΠΊΠ΅ΡΠ°
DOCKER_CERT_PATH=/root/.docker
# ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌ, ΡΡΠΎ Π² ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ΅ Π²ΡΠ΅ ΠΈΠΌΠ΅Π΅ΡΡΡ
docker info
docker-compose version
# ΡΠΎΠ·Π΄Π°Π΅ΠΌ ΠΏΡΡΡ (ΡΠ΅ΠΉΡΠ°Ρ ΡΠ°Π±ΠΎΡΠ°Π΅ΠΌ Π² ΠΊΠ»ΠΈΠ΅Π½ΡΠ΅ - Π²ΠΎΡΠΊΠ΅ΡΠ΅ gitlab'Π°)
mkdir $DOCKER_CERT_PATH
# ΠΈΠ·ΡΠΌΠ°Π΅ΠΌ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
, ΠΏΡΠΈ ΡΡΠΎΠΌ ΡΠ΄Π°Π»ΡΠ΅ΠΌ Π»ΠΈΡΠ½ΠΈΠ΅ ΡΠΈΠΌΠ²ΠΎΠ»Ρ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Π½ΡΠ΅ ΠΏΡΠΈ ΡΠΎΡ
ΡΠ°Π½Π΅Π½ΠΈΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
.
echo "$CA_PEM" | tr -d 'r' > $DOCKER_CERT_PATH/ca.pem
echo "$CERT_PEM" | tr -d 'r' > $DOCKER_CERT_PATH/cert.pem
echo "$KEY_PEM" | tr -d 'r' > $DOCKER_CERT_PATH/key.pem
# Π½Π° Π²ΡΡΠΊΠΈΠΉ ΡΠ»ΡΡΠ°ΠΉ Π΄Π°Π΅ΠΌ ΡΠΎΠ»ΡΠΊΠΎ ΡΠΈΡΠ°ΡΡ
chmod 400 $DOCKER_CERT_PATH/ca.pem
chmod 400 $DOCKER_CERT_PATH/cert.pem
chmod 400 $DOCKER_CERT_PATH/key.pem
# Π΄Π°Π»Π΅Π΅ Π½Π°ΡΠΈΠ½Π°Π΅ΠΌ ΡΠΆΠ΅ ΡΠ°Π±ΠΎΡΠ°ΡΡ Ρ ΡΠ΄Π°Π»Π΅Π½Π½ΡΠΌ docker-Π΄Π΅ΠΌΠΎΠ½ΠΎΠΌ. Π‘ΠΎΠ±ΡΡΠ²Π΅Π½Π½ΠΎ, ΡΠ°ΠΌ Π΄Π΅ΠΏΠ»ΠΎΠΉ
export DOCKER_TLS_VERIFY=1
export DOCKER_HOST=tcp://$DEPLOY_HOST:2376
# ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌ, ΡΡΠΎ ΠΊΠΎΠ½Π½Π΅ΠΊΡΠΈΡΡΡ Π²ΡΠ΅ ΡΡΠΏΠ΅ΡΠ½ΠΎ
docker-compose
-f $DOCKER_COMPOSE_FILE
ps
# Π»ΠΎΠ³ΠΈΠ½ΠΈΠΌΡΡ Π² docker-ΡΠ΅Π³ΠΈΡΡΡΠΈ, ΡΡΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΡΠΊΠ°Π·Π°ΡΡ ΡΠ²ΠΎΠΉ "ΠΌΠ΅ΡΡΠ½ΡΠΉ" ΡΠ΅Π³ΠΈΡΡΡΠΈ
docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
docker-compose
-f $DOCKER_COMPOSE_FILE
pull app
# ΠΏΠΎΠ΄Π½ΠΈΠΌΠ°Π΅ΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅
docker-compose
-f $DOCKER_COMPOSE_FILE
up -d app
The main issue was to "extract" the contents of the certificates from the GitLab CI/CD variables in a normal form. I couldn't understand why the connection to the remote host was not working. I checked the log on the host with sudo journalctl -u docker, and there was an error during the handshake. I decided to see what was actually stored in the variables, so I checked with cat -A $DOCKER_CERT_PATH/key.pem. I resolved the error by removing the carriage return character with tr -d 'r'.
You can add post-release tasks to the script at your discretion. You can familiarize yourself with the working version in my repository.
Source: habr.com
