Введение
GitLab является платформой для совместной работы команд разработчиков и проектом с открытым исходным кодом, в котором реализованы различные полезные функции для DevOps и где можно размещать репозиторий кода. Также платформа предоставляет возможность для отслеживания проблем, размещения пакетов и реестров, сопровождения Wiki, настраивания конвейеров непрерывной интеграции и развертывания (CI/CD).
В этой инструкции рассмотрим создание конвейера непрерывного развертывания с помощью платформы GitLab. Настроим его при создании образа Docker, разместим в реестр контейнеров GitLab и развернем на собственном сервере, используя утилиту SSH. Запуск конвейера будет для всех фиксаций, размещенных в репозиториях.
Необходимо развернуть статическую web-страницу, но в данной инструкции большое внимание будет обращено на настройку конвейера непрерывного развертывания.
После выполнения всех шагов в этой инструкции, мы сможем посетить нашу платформу, введя в адресную строку браузера IP-адрес нашего сервера для получения результатов автоматического развертывания.
Подготовка к работе
С необходимыми требованиями для развертывания GitLab на своем сервере, вы можете ознакомиться на официальном сайте проекта.
Также вам необходимо развернуть сервер на базе Ubuntu/Debian/CentOS. Настроить брандмауэр и добавить пользователя с правами доступа на выполнения команд, используя sudo.
Установить Docker согласно нашей инструкции.
Зарегистрироваться на сайте GitLab для развертывания своего проекта, либо развернуть в собственном сервере, как показано в нашем руководстве.
Создание репозитория в GitLab
Первым шагом является создание нового проекта в репозитории. Создадим в нём HTML файл. Позже этот файл скопируем в образ Nginx Docker, который мы развернем на собственном сервере.
Авторизуйтесь в платформе и создайте проект.

Выберем Create blank project.

Укажем название проекта, URL проекта, видимость проекта и нажмём на кнопку Create project.

Создадим новый файл с помощью кнопки New file.

Укажем в названии файла index.html и вставим наш код:
<!doctype html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>GitLab ServerSpace</title>
</head>
<body>
<h1>Our project in GitLab</h1>
</body>
</html>
Необходимо сохранить изменения с помощью кнопки Commit. Укажем название нашего изменения и щелкнем по кнопке Commit.
В этом коде создается пустая страница с одним заголовком, отображающим при открытии страницы надпись Our project in GitLab.
Создадим Dockerfile и скопируем файл index.html в образ web-сервера Nginx.
Вернемся на страницу нашего проекта и создадим новый файл.
Укажем в названии Dockerfile и вставим следующий код.
FROM nginx:1.18
COPY index.html /usr/share/nginx/html

В параметре FROM обращаемся к образу для наследования, в нашем случае образ nginx:1.18. Необходимо указывать версии образов, при указании параметра latest, могут возникнуть проблемы при сборке проекта.
Параметр COPY копирует ранее созданный index.html в /usr/share/nginx/html в образе Docker. В этом каталоге будут храниться статические страницы HTML-файлов.
Внесём изменения в репозиторий, нажав на кнопку Commit.
В следующем шаге рассмотрим настройку GitLab Runner для контроля выполнения заданий по развертыванию.
Настройка агента GitLab Runner
Отслеживание среды происходит следующим образом, необходимо зарегистрировать свой сервер, как исполнителя GitLab с закрытым ключом SSH.
При использовании SSH для входа на свой сервер конвейера развертывания, необходимо сохранить приватный ключ SSH в нашей переменной GitLab CI/CD (рассматривается в шаге Хранение ключа в переменной GitLab).
Приватный ключ SSH является конфиденциальной частью данных и считается пропуском на сервер. Необходимо обезопасить его и сделать так, чтобы он не попал в чужие руки.
Мы рассматриваем иную ситуацию, нам нужно предоставить ключ платформе GitLab для доступа к нашему серверу, чтобы автоматизировать процесс развертывания.
GitLab Runner считается агентом платформы GitLab, который будет выполнять вход на наш сервер, используя приватный ключ. Каждый конвейер GitLab использует агентов, которых будем указывать в конфигурации CI/CD, для выполнения заданий. Задание развертывания будет выполняться на исполнителе GitLab, по этой причине приватный ключ будет размещен на стороне исполнителя для получения доступа к серверу с помощью SSH.
Авторизуемся в нашем сервере:
ssh serverspace@server-host-IP
Установка утилиты gitlab-runner производится путём скачивания скриптового файла и запуска.
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh > script.deb.sh
Запустим файл script.deb.sh с помощью командного интерпретатора bash:
bash script.deb.sh

Установим утилиту с помощью apt:
apt install gitlab-runner
После установки получим результат:

Перейдём в репозиторий проекта и скопируем Token проекта. Перейдём в раздел Settings – CI/CD – Runners. В Set up a specific Runner manually скопируем наш токен и URL адрес в текстовый документ.

Вернемся в командную строку нашего сервера и введём следующую команду, используя ранее скопированные данные нашего проекта:
gitlab-runner register -n --url https://your_gitlab.com --registration-token project_token --executor docker --description "Deployment Runner" --docker-image "docker:stable" --tag-list deployment --docker-privileged
В результате получим:

-n — регистрирует не интерактивно (все параметры выполняются как опции команды);
–url — адрес GitLab;
–registration-token — токен из репозитория;
–executor — тип исполнителя;
–description — описание;
–docker-image — образ Docker;
–tag-list — список тегов;
–docker-privived – запуск контейнера Docker.
Если перейдём в раздел Settings – CI/CD – Runners можем получить результат авторизации нашего агента GitLab-Runner:

Создание пользователя для развертывания
После успешной авторизации необходимо добавить пользователя в сервер, который будет выполнять задания для развертывания:
useradd -m dep-user
passwd dep-user
Добавим пользователя в группу Docker.
usermod -aG docker dep-user
Теперь наш пользователь может выполнять команды, используя docker.
Настройка ключа SSH
Необходимо переключиться на пользователя dep-user и сгенерировать ключ SSH.
При выполнении команды укажем путь, где будет сохранён ключ, укажем пароль и повторим:
ssh-keygen -b 4096
Получим результат:

В следующем шаге рассмотрим добавления ключа в настройках репозитория, сделав его доступным при обработке процесса непрерывного развертывания нашего конвейера.
Копирование ключа в репозиторий проекта
Нам нужно хранить приватный ключ в платформе GitLab для конвейера, который использует ключ для входа на сервер.
GitLab добавляет конвейер CI/CD и отправляет все данные исполнителю, которые будут установлены на время выполнения задания.
Посмотрим наш созданный ключ:
cat .ssh/authorized_keys
Скопируем наш ключ и перейдём в Settings – CI/CD – Variables и добавим переменную (Add variable).
Key: ID_RSA
Value: Скопированный ключ
Type: File
Environment scope: All
Flags:
- Protect variable – поставить галочку
- Mask variable – снять галочку
Таким образом, добавим адрес нашего сервера и пользователя:
Key: SERVER_IP
Value: IP-адрес сервера
Type: Variable
Environment scope: All
Flags:
- Protect variable – поставить галочку
- Mask variable – поставить галочку
Key: SERVER_USER
Value: dep-user
Type: Variable
Environment scope: All
Flags:
- Protect variable – поставить галочку
- Mask variable – поставить галочку
В следующем шаге рассмотрим описание файла gitlab-ci.yml.
Конфигурирование gitlab-ci.yml
Мы собираемся развернуть конвейер, который создаст образ Docker и отправит в реестр контейнеров. В GitLab имеется реестр контейнеров для каждого проекта отдельно. Про реестр контейнеров, можно подробнее изучить, перейдя в раздел Packages & Registers -> Container registry в своём проекте. Можно также воспользоваться официальной документацией GitLab.
В репозитории проекта создадим файл с названием .gitlab-ci.yml, который будет содержать конфигурацию нашего конвейера.
Добавим конфигурацию:
stages:
- publish
- deploy
Каждое задание закрепляется за этапом (stages). Задания, которые назначаются одному и тому же этапу (stages), выполняются параллельно. Этапы выполняются в том порядке как указываются. В данном этапе публикация рассматривается первой и за ним развертывание.
Новые этапы (stages) начинают выполняться после успешного выполнения предыдущего этапа.
Добавим следующую конфигурацию после записанного этапа:
variables:
TAG_LATEST: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:latest
TAG_COMMIT: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA
CI_REGISTRY_IMAGE: это URL-адрес нашего реестра для контейнеров, которые привязаны к конкретному проекту.
CI_COMMIT_REF_NAME: наименование ветки либо тега, где будет создаваться проект.
CI_COMMIT_SHORT_SHA: первые восемь символов ревизии фиксации, для которой создается проект.
TAG_LATEST: добавляет образ к последнему тегу.
В $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME указывается имя образа Docker по умолчанию. В документации GitLab, название образа Docker должно соответствовать следующей схеме:
image name scheme
<registry URL>/<namespace>/<project>/<image>
Далее внесём изменения в gitlab-ci.yml и добавим следующий код:
publish:
image: docker:latest
stage: publish
services:
- docker:dind
script:
- docker build -t $TAG_COMMIT -t $TAG_LATEST .
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
- docker push $TAG_COMMIT
- docker push $TAG_LATEST
Элемент Publish является первым заданием в нашей конфигурации непрерывного интегрирования и развертывания и хранит в себе несколько команд, которые рассмотрим ниже:
image – Docker образ, который используется в этой инструкции.
stage – назначает задание стадии публикации.
services – обозначает Docker-in-Docker. По этой причине мы зарегистрировали GitLab-Runner в привилегированном режиме.
Рабочий каталог будет установлен в корень репозитория, когда эти команды будут выполнены.
docker build: создает образ Docker на основе файла Dockerfile и помечает его последним тегом фиксации, определенным в разделе переменных.
docker login: регистрирует Docker в реестре контейнеров проекта.
docker push: отправляет оба тега образа в реестр контейнеров.
Добавим конфигурацию для развертывания в файл gitlab-ci.yml
deploy:
image: debian:latest
stage: deploy
tags:
- deployment
script:
- sudo apt update && apt install openssh-server
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker pull $TAG_COMMIT"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker container rm -f ServerSpace || true"
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP "docker run -d -p 80:80 --name ServerSpace $TAG_COMMIT"
Alpine – является облегченным дистрибутивом для образа Docker.
В разделе script запускается две конфигурационные команды:
- chmod og= $ID_RSA: для отмены всех разрешений группы и других лиц без приватного ключа.
- apk update && apk add openssh-client: APK является пакетным менеджером заданного дистрибутива и в данной команде обновляет информацию о пакетах и устанавливает утилиту ssh клиент.
Затем используются команды ssh из шаблона:
- ssh connect pattern for all deployment commands
- ssh -i $ID_RSA -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP “command”
-i оператор означает файл идентификации
– $ID_RSA считается переменным GitLab, в котором содержится путь к файлу приватного ключа.
-o StrictHostKeyChecking=no: с помощью этого оператора мы автоматически пропускаем вопросы о доверие к удаленному хосту.
$SERVER_USER и $SERVER_IP — ранее созданные переменные, к которым мы прикрепили имя пользователя и адрес нашего сервера для подключения по SSH.
Добавим наш последний кусок кода, в котором укажем среду развертывания (environment), название среды (production), адрес нашего сервера (url) и единственный раздел (only):
environment:
name: production
url: http://host-address
only:
- main

Сохраним наши изменения нажав на Commit changes.
Тестирование развертывания
На этом этапе рассмотрим развертывание в разных платформах GitLab, на нашем сервере и в браузере.
После добавления gitlab-ci.yml в репозиторий, GitLab автоматически обнаружит и запустит конвейер.
Необходимо перейти в раздел CI/CD -> Pipelines в проекте для просмотра статуса конвейера. В списке конвейеров можем увидеть статус своего проекта Passed. Иногда требуется неопределенное количество времени для завершения запуска конвейера.
После завершения под столбцом Stages должны появиться две галочки:

Более подробно можем получить информацию о процессе развертывания с помощью нажатия на «passed» под разделом «Status», и мы получим следующие данные:
- получим информацию о времени выполнения конвейера;
- название коммита и ветки;
- задания, которые выполнялись в этом конвейере и их состояние;
Рассмотрим статус развертывания.

Если прокрутить страницу вверх, мы увидим сообщение о том, что это задание развернуто в рабочей среде. Если нажать на кнопку deploy, то перейдём в раздел с результатами стадии развертывания.

Процесс повторного развертывания зависит от конфигурации нашего конвейера. Наш конвейер может повторно выполнять те же задания, которые были указаны в .gitlab-ci.yml.
Если нажать на кнопку «Посмотреть развертывание» (View deployment), то откроется страница с адресом нашего сервера, и увидим надпись «Our project in GitLab».
Для проверки развернутого контейнера перейдём на наш сервер и подключимся по ssh.
Далее проверим список контейнеров с помощью команды:
docker container ls
И получим следующий результат
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba1a841c23d4 registry.gitlab-server.com/authorized_user_of_gitlab/serverspace/master:commit "nginx -g 'daemon of..." 4 hours ago Up 4 hours 0.0.0.0:80->80/tcp gitlab-serverspace
Также предлагаем ознакомиться с нашей инструкцией по «Установке и настройке Docker».
На следующем этапе рассмотрим откат развертывания.
Откат непрерывного развертывания
Если обновить веб-страницу, создастся новое развертывание, а затем повторно развернет предыдущее развертывание с использованием сред GitLab. Тем самым охватывает вариант использования отката развертывания в случае ошибочного развертывания.
Необходимо внести в файле index.html внести небольшое изменение:
- Перейдём в репозиторий проекта с файлом index.html.
- Нажмем кнопку «Редактировать» для открытия редактора конвейера.
- Удалим старый код и добавим новый:
<html>
<body>
<h1>Successful</h1>
</body>
</html>
Необходимо сохранить изменения с помощью кнопки «Commit changes».
Запустится новый конвейер развертывания. В GitLab перейдём в раздел CI/CD > Pipelines. После успешного завершения заданий в конвейере необходимо открыть web-страницу по адресу нашего сервера, в котором отображается надпись Successful.
Если перейти в раздел Deployments > Environments > production, отображается новый созданный конвейер развертывания. Теперь нажмем кнопку повторного развертывания конвейера для отката на исходное состояние:

Необходимо подтвердить откат во всплывающем окне.
Наш конвейер развертывания запустит процесс обратного отката и перенаправит автоматически на страницу с результатами выполненного задания. Необходимо подождать до завершения задания и открыть web-страницу, указав адрес нашего сервера в браузере. В итоге будет отображаться старая надпись «Our project in GitLab».
Выводы
В этой инструкции мы рассмотрели:
- создание проекта на сайте GitLab;
- установку и настройку GitLab на своём сервере;
- привязку gitlab-runner по SSH ключу на платформе GitLab;
- описание gitlab-ci.yml с заданиями;
- описание Dockerfile для запуска образа nginx в контейнере на сервере;
- запуск процесса непрерывной интеграции и развертывания;
- откат процесса развертывания web-страницы.