Setting up a CD via gitlab

  • Tutorial
Once I thought about automating the deployment of my project. kindly provides all the tools for this, and of course I decided to use it by sorting out and writing a small deployment script. In this article, I share my experience with the community.


  1. Configure VPS: disable root, password login, install dockerd, configure ufw
  2. Generate certificates for server and client Enable dockerd control via tcp socket: remove the -H fd option: / / from docker config.
  3. Register certificate paths in docker.json
  4. Register in gitlab variables in CI / CD settings with certificate contents. Write a .gitlab-ci.yml script for the deployment.

I will show all examples on the Debian distribution kit.

Initial VPS Setup

So you bought an instance for example on DO , the first thing to do is to protect your server from the aggressive outside world. I will not prove and claim anything, just show the log / var / log / messages of my virtual server:


First, install the ufw firewall:

apt-get update && apt-get install ufw

Turn on the default policy: block all incoming connections, allow all outgoing connections:

ufw default deny incoming
ufw default allow outgoing

Important: do not forget to allow ssh connection:

ufw allow OpenSSH

The general syntax is: Allow a port connection: ufw allow 12345, where 12345 is the port number or the name of the service. Deny: ufw deny 12345

Turn on the firewall:

ufw enable

We leave the session and log in again via ssh.

Add the user, assign him a password and add him to the sudo group.

apt-get install sudo
adduser scoty
usermod -aG sudo scoty

Next, according to the plan, you must disable the password entry. To do this, copy your ssh key to the server:

ssh-copy-id root@

Your server ip must be specified. Try now to log in under the user created earlier, you no longer need to enter a password. Next, in the configuration settings, change the following:

sudo nano /etc/ssh/sshd_config

disable password entry:

PasswordAuthentication no

Restart the sshd daemon:

sudo systemctl reload sshd

Now, if you or someone else tries to log in as root, it won’t work.

Next, set dockerd, I won’t describe the process here, since everything can already be changed, follow the link to the official website and go through the steps to install docker on your virtual machine: ce / debian /

Certificate Generation

To manage the docker daemon remotely, an encrypted TLS connection is required. To do this, you must have a certificate and a key, which must be generated and transferred to your remote machine. Follow the steps given in the instructions on the official docker website: All generated * .pem files for the server, namely ca.pem, server.pem, key.pem must be placed in the / etc / docker directory on the server.

Dockerd setup

In the script to launch the docker daemon, remove the -H df: // option, this option answers which host can control the docker daemon.

# At /lib/systemd/system/docker.service

Next, create a settings file, if it is not already there and prescribe options:

  "hosts": [
  "labels": [
  "tls": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server.pem",
  "tlskey": "/etc/docker/key.pem",
  "tlsverify": true

Let's enable connections on port 2376:

sudo ufw allow 2376

Restart dockerd with the new settings:

sudo systemctl daemon-reload && sudo systemctl restart docker


sudo systemctl status docker

If everything is green, then we believe that we have successfully configured docker on the server.

Configuring continuous deleivery on gitlab

In order for the gitalab worker to be able to execute commands on the docker's remote host, it is necessary to determine how and where to store certificates and the key for an encrypted connection with dockerd. I solved this problem by simply writing it into variables in the gitlbab settings:

Spoiler heading

Just displays the contents of the certificate and key through the cat: cat ca.pem. Copy and paste into the value of the variables.

Let's write the script for the deployment through gitlab. The docker-in-docker (dind) image will be used.

  name: docker/compose:1.23.2
  # перепишем entrypoint , чтобы работало в dind
  entrypoint: ["/bin/sh", "-c"]
  DOCKER_HOST: tcp://docker:2375/
  DOCKER_DRIVER: overlay2
  - docker:dind
  - deploy
  stage: deploy
    - bin/ # скрипт деплоя тут

The content of the deployment script with comments:

bin /
#!/usr/bin/env sh
# Падаем сразу, если возникли какие-то ошибки
set -e
# Выводим, то , что делаем
set -v
# Куда деплоим
# Путь для сертификатов клиента, то есть в нашем случае - gitlab-воркера
# проверим, что в контейнере все имеется
docker info
docker-compose version
# создаем путь (сейчас работаем в клиенте - воркере gitlab'а)
# изымаем содержимое переменных, при этом удаляем лишние символы добавленные при сохранении переменных.
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_HOST=tcp://$DEPLOY_HOST:2376
# проверим, что коннектится все успешно
docker-compose \
# логинимся в docker-регистри, тут можете указать свой "местный" регистри
docker login -u $DOCKER_USER -p $DOCKER_PASSWORD
docker-compose \
  pull app
# поднимаем приложение
docker-compose \
  up -d app

The main problem was to “extract” the contents of certificates in normal form from gitlab CI / CD variables. I could not understand why the connection to the remote host did not work. On the host, I looked at the sudo journalctl -u docker log, there is a handshake error. I decided to look at what is generally stored in variables, for this you can see cat -A $ DOCKER_CERT_PATH / key.pem. The error was overcome by adding the removal of the carriage symbol tr -d '\ r'.

Further in the script, you can add post-release tasks at your discretion. You can see the working version in my repository

Also popular now: