Сделал свою первую работающую пипелину под GitLab на проекте «hello». Она небольшая, но умеет довольно много:

  • собирает docker-образ Nginx, выводя на главной странице SHA коммита
  • запускает его на порту, который определен в переменных проекта GitLab
  • настраивает необходимым образом реверс-прокси сервер

Выглядит она так:

stages:
  - build
  - deploy

build docker image:
  stage: build
  tags:
    - docker-image-builder
  script:
    - echo "Commit SHA ${CI_COMMIT_SHA}" >> public/index.html
    - docker build . -f docker/nginx/Dockerfile -t hello_nginx:${CI_COMMIT_SHA}

run docker container:
  stage: deploy
  tags:
    - deploy
  script:
    - docker stop hello_from_ci || true
    - docker run --rm -d -p ${HTTP_PORT}:80 --name hello_from_ci hello_nginx:${CI_COMMIT_SHA}

setup Caddy:
  stage: deploy
  when: manual
  tags:
    - deploy
  script:
    - envsubst < deploy/caddy/hello.deb24.ru | sudo tee /etc/caddy/sites-enabled/hello.deb24.ru
    - sudo service caddy reload

Во-первых, я использовал человекочитаемые названия: «setup Caddy», а не «setup_caddy», как принято на работе. Посмотрим, насколько это удобно.

Во-вторых, два шага этапа deploy запускаются параллельно, причем один из шагов — в ручном режиме.

В-третьих, в этой скромной пипелине есть довольно много: от использования переменных до запуска операций с sudo.

build docker image

Вначале я думал использовать docker runner для сборки образа. Но затем не стал заморачиваться и сделал на shell-раннере. На данный момент теги «docker-image-builder» и «deploy» относятся к одному и тому же shell-раннеру. Возможно, что в будущем собирать образы будет отдельный раннер на основе dind. Его можно сделать так (уже не помню, я взял откуда-то или написал сам):

FROM docker:dind

RUN apk add --no-cache bash git dumb-init gitlab-runner && \
    mkdir /home/gitlab-runner

ENTRYPOINT ["/usr/bin/dumb-init", "gitlab-runner"]

CMD ["run", "--working-directory=/home/gitlab-runner"]

Но вернемся к пипелине. На этом этапе интересно тегирование образа хешем коммита:

-t hello_nginx:${CI_COMMIT_SHA}

А на этапе запуска контейнера используется тот же самый хеш. Таким образом, можно взять какую-то прошлую пипелину, запустить стадию deploy заново, и главная страница откатится до версии на момент той самой сборки — это проверено. Выглядит так:

# Какая-то старая версия (и тут запустили deploy из истории) - показывается
Hello from CI/CD!!!
New uuid 5be560cd43c14eb6f8fedd1e9f5e05ff8e6eaf04

# Версия из последнего коммита - заменена старой версией, не показывается
Hello from CI/CD!!!
New uuid 1737b23dd8955132d11a0ceaf6b2a48eb78b4bc2

run docker container

На этом шаге происходит остановка прошлого контейнера и запуск нового, на основе собранного образа:

    - docker stop hello_from_ci || true
    - docker run --rm -d -p ${HTTP_PORT}:80 --name hello_from_ci hello_nginx:${CI_COMMIT_SHA}

Предварительно следует добавить раннеру права на работу с docker:

sudo usermod -aG docker gitlab-runner

setup Caddy

Этот шаг настраивает веб-сервер Caddy, который я использую в режиме реверс-прокси. Настройка одноразовая, поэтому выбран manual запуск. Однако при смене порта нужно запустить этот шаг повторно.

Настроить и перезапустить Caddy можно еще до старта контейнера приложения, поэтому шаг выполняется одновременно с этим самым запуском приложения. Проще говоря, пока приложение все еще стартует, можно запустить конфигурирование реверс-прокси:

    - envsubst < deploy/caddy/hello.deb24.ru | sudo tee /etc/caddy/sites-enabled/hello.deb24.ru
    - sudo service caddy reload

Конфигурирование заключается в подстановке номера порта через envsubst в очень простой конфиг:

hello.deb24.ru {
    reverse_proxy :$HTTP_PORT
}

Этот конфиг записывается в кастомный каталог /etc/caddy/sites-enabled. А чтобы Caddy этот каталог учитывал, в /etc/caddy/Caddyfile необходимо добавить это:

import sites-enabled/*

Для перезапуск сервиса нужны root-привилегии, которыми надо снабдить gitlab-runner:

sudo visudo
# добавить эту строку:
gitlab-runner   ALL=(ALL:ALL) NOPASSWD: ALL

Этот опыт ответил на некоторые мои вопросы. Но возникли новые мысли:

  • Можно ли сделать крон-задачи на GitLab?
  • Сделать сборку в отдельном dind runner, используя buildx / Docuum
  • Подключить какое-то хранилище паролей. variables хорошо, но хотелось бы возможность сохранить все пароли себе куда-то в файл на случай тотального падения. Код можно будет достать из bitbucket, а креды — из этого файла.
  • Реально запустить какой-то свой проект: tendera online, mailtester или lucky.

От debitos

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *