Стабильно

Запуск GitLab Runner с исполнителем Docker

Как запустить GitLab Runner с исполнителем Docker для GitLab на собственном сервере, отделить служебный трафик CI от браузерного доступа и устранить ошибки реестра пакетов.

Шаги

Выполняйте по порядку.

  1. 01Разделить браузерный и служебный трафик CIНаправляйте браузерный доступ пользователей через BusinessProxy, а для GitLab Runner и контейнеров заданий используйте закрытый служебный маршрут.
  2. 02Запустить и зарегистрировать GitLab RunnerХраните конфигурацию вне контейнера, закрепите версию образа, используйте отдельную сеть Docker и вводите токен только по запросу команды регистрации.
  3. 03Организовать внутренний HTTPSПринимайте HTTPS-соединения на внутреннем TLS-прокси и передавайте запросы в HTTP-сервис GitLab, не открывая дополнительный порт сервера.
  4. 04Переключить без прерывания заданийСначала проверьте TLS-прокси, перенесите основной сетевой псевдоним, обновите все записи GitLab Runner и сохраните копию для отката.
  5. 05Проверить и диагностировать публикациюОтличайте ошибки DNS и TLS от ошибок авторизации GitLab, затем проверьте настройку с помощью реального задания для реестра пакетов.

Справочник

Детали реализации для настройки и проверки.

Когда использовать эту инструкциюИспользуйте эту инструкцию, когда GitLab, развёрнутый на собственном сервере, доступен пользователям через BusinessProxy App Gateway, а GitLab Runner с исполнителем Docker работает на том же сервере или в той же закрытой сети. Браузерный доступ и служебный трафик CI используют разные механизмы аутентификации, поэтому GitLab Runner не должен зависеть от браузерной сессии BusinessProxy.
  • Параметр external_url остаётся основным HTTPS-адресом GitLab, например https://gitlab.example.com.
  • Контейнер GitLab может продолжать принимать соединения на HTTP-порту 80 внутри закрытой сети Docker.
  • Получение заданий GitLab Runner, клонирование репозиториев и обращения к реестру пакетов проходят по закрытому внутреннему HTTPS-маршруту и не зависят от многофакторной проверки в браузере или сессии App Gateway.
Маршруты и граница доверияИспользуйте одно основное доменное имя, но два контролируемых маршрута. Запросы из внешних браузеров проходят через BusinessProxy и исходящий коннектор. Для GitLab Runner и контейнеров заданий служба DNS сопоставляет это же имя с внутренним TLS-прокси, который передаёт запросы в HTTP-сервис GitLab.
Браузер -> BusinessProxy App Gateway -> GitLab HTTP :80
Runner/задание -> внутренний TLS-прокси :443 -> GitLab HTTP :80
  • Внутри сети Docker имя gitlab.example.com назначено только TLS-прокси.
  • GitLab сохраняет отдельный служебный псевдоним, например gitlab, чтобы TLS-прокси обращался к http://gitlab:80.
  • Не публикуйте TLS-прокси через параметры -p или ports: это внутренний адрес для CI, а не ещё одна публичная точка входа GitLab.
1. Создайте сеть и запустите GitLab RunnerИспользуйте отдельную сеть Docker и сохраняйте содержимое /etc/gitlab-runner вне контейнера. Закрепите проверенную версию образа GitLab Runner и не используйте изменяемый тег latest.
docker network create gitlab-internal
docker network connect --alias gitlab gitlab-internal gitlab

docker run -d --name gitlab-runner \
  --restart unless-stopped \
  --network gitlab-internal \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \
  gitlab/gitlab-runner:alpine-v<проверенная-версия>
  • Подключение сокета Docker даёт GitLab Runner полный контроль над узлом Docker. Используйте выделенный сервер, назначайте GitLab Runner только доверенным проектам и разрешайте ему выполнять задания только для защищённых веток и тегов.
  • Задайте политику перезапуска и следите за свободным местом: образы контейнеров и кэш сборок накапливаются на сервере.
  • Не выполняйте docker network create или docker network connect, если сеть или подключение уже существуют. Сначала проверьте текущие сетевые псевдонимы и сохраните те, которые не относятся к этой настройке.
2. Настройте внутренний TLS-проксиTLS-прокси должен предъявлять сертификат, действительный для основного доменного имени, и передавать запросы в HTTP-сервис GitLab по закрытой сети Docker. Подключайте файлы сертификата и конфигурации только для чтения.
events {}
http {
  upstream gitlab_backend { server gitlab:80; }
  server {
    listen 443 ssl;
    server_name gitlab.example.com;
    ssl_certificate /certs/fullchain.pem;
    ssl_certificate_key /certs/privkey.pem;
    client_max_body_size 0;

    location / {
      proxy_pass http://gitlab_backend;
      proxy_http_version 1.1;
      proxy_set_header Host gitlab.example.com;
      proxy_set_header X-Forwarded-Proto https;
      proxy_set_header X-Forwarded-For $remote_addr;
      proxy_request_buffering off;
      proxy_buffering off;
      proxy_read_timeout 3600s;
      proxy_send_timeout 3600s;
    }
  }
}
  • Заголовки Authorization, JOB-TOKEN и DEPLOY-TOKEN должны доходить до GitLab без изменений. Не переопределяйте их в конфигурации TLS-прокси.
  • После обновления сертификата проверяйте конфигурацию nginx перед его перезагрузкой. Не используйте просроченный сертификат или сертификат для другого имени.
3. Запустите TLS-прокси без внешнего портаПодключите каталог с сертификатом, а не копируйте закрытый ключ в образ. На время проверки запустите контейнер с временным внутренним псевдонимом; перенесите на него основной псевдоним только после успешной проверки.
docker run -d --name gitlab-internal-tls \
  --restart unless-stopped \
  --network gitlab-internal \
  --network-alias gitlab-internal-tls \
  -v /srv/gitlab-internal-tls/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v /secure/certs/gitlab.example.com:/certs:ro \
  nginx:1.27-alpine
  • Не добавляйте -p 443:443. GitLab Runner и контейнеры заданий подключаются к TLS-прокси по сети gitlab-internal.
  • После продления сертификата автоматически проверяйте конфигурацию командой nginx -t и перезагружайте nginx командой nginx -s reload. Заранее предупреждайте администратора об окончании срока действия сертификата.
4. Безопасно перенесите сетевой псевдонимНе меняйте сетевые псевдонимы Docker во время активного задания. Сначала проверьте TLS-прокси по IP, затем удалите основной псевдоним из настроек контейнера GitLab, принимающего только HTTP, и назначьте его только TLS-прокси. Сохраните прежнее распределение псевдонимов для отката.
curl --resolve gitlab.example.com:443:<sidecar-ip> \
  https://gitlab.example.com/users/sign_in

docker network inspect gitlab-internal
  • Не добавляйте -k к предварительной проверке: тест должен проверить имя и доверие к сертификату.
  • После переноса псевдонима перезапустите TLS-прокси, чтобы он заново определил адрес GitLab с учётом итоговой конфигурации сети.
  • Ожидаемые ответы GitLab: страница HTML с кодом 200, обычное перенаправление или код 401 для защищённого адреса API, но не страница ошибки BusinessProxy.
5. Зарегистрируйте GitLab Runner без раскрытия токенаСоздайте GitLab Runner в интерфейсе GitLab только после проверки внутреннего HTTPS-маршрута, затем выполните интерактивную регистрацию. Так токен аутентификации не попадёт в документацию, историю командной оболочки или журналы процессов.
docker exec -it gitlab-runner gitlab-runner register \
  --url https://gitlab.example.com \
  --executor docker \
  --docker-image node:22-alpine \
  --description private-docker-runner
  • Вводите токен аутентификации только по запросу команды регистрации и ограничьте права доступа к полученному файлу config.toml.
  • Не выводите токен аутентификации или полный файл config.toml в журналы CI и обращения в поддержку.
6. Настройте все записи GitLab RunnerДля получения заданий и клонирования репозиториев используйте основной HTTPS-адрес. В разделе Docker также задайте параметр network_mode, поскольку исполнитель запускает отдельные контейнеры для заданий и служебных операций.
[[runners]]
  url = "https://gitlab.example.com"
  clone_url = "https://gitlab.example.com"
  executor = "docker"

  [runners.docker]
    image = "node:22-alpine"
    network_mode = "gitlab-internal"
  • В рабочей конфигурации также есть токен аутентификации GitLab Runner; в примере он намеренно не показан.
  • Обновите все записи в config.toml. Даже одна устаревшая запись может продолжить получать задания или клонировать репозитории по неправильному маршруту.
7. Проверьте соединение из контейнеров GitLab Runner и заданияПроверьте DNS и TLS из обоих контейнеров. Проверки только из контейнера GitLab Runner недостаточно, поскольку исполнитель Docker запускает задания в отдельных контейнерах.
docker exec gitlab-runner getent hosts gitlab.example.com
docker exec gitlab-runner gitlab-runner verify

docker run --rm --network gitlab-internal curlimages/curl:<проверенная-версия> \
  -I https://gitlab.example.com/users/sign_in
  • Внутри сети gitlab-internal имя должно указывать только на адрес TLS-прокси.
  • Запустите тестовый конвейер CI, который клонирует репозиторий и публикует или скачивает пакет. Считайте настройку подтверждённой только после успешного завершения задания.
ECONNREFUSED на частном адресе и порту 443Ошибка вида connect ECONNREFUSED 172.x.x.x:443 обычно означает, что внутренняя служба DNS Docker сопоставила gitlab.example.com непосредственно с контейнером GitLab, а встроенный nginx GitLab принимает соединения только на HTTP-порту 80. Запрос не дошёл до BusinessProxy или его внешнего контура.
  • Проверьте сетевые псевдонимы каждого контейнера в gitlab-internal и удалите основной псевдоним у контейнера GitLab, принимающего только HTTP.
  • Назначьте основной псевдоним TLS-прокси и перезапустите GitLab Runner после изменения config.toml.
  • Не меняйте external_url на HTTP и не отключайте проверку сертификата, чтобы скрыть ошибку маршрутизации.
Другие ошибки GitLab Runner и реестра пакетов
  • Ошибка x509 или несовпадение имени узла: исправьте имена в поле SAN сертификата, цепочку доверия или файл сертификата, подключённый к контейнеру; не отключайте проверку TLS.
  • 401 Unauthorized: DNS и TLS работают; проверьте CI_JOB_TOKEN, токен развёртывания, права проекта и политику реестра пакетов.
  • 404 Not Found: проверьте идентификатор проекта, путь пакета, используемый адрес API и включён ли реестр пакетов для проекта.
  • POST /api/v4/jobs/request возвращает 204: GitLab Runner работает, но в GitLab нет подходящего задания, ожидающего выполнения.
  • GitLab Runner получает задание, но клонирование или npm publish завершается ошибкой: убедитесь, что к сети gitlab-internal подключены также вспомогательные контейнеры и контейнеры заданий, а не только контейнер GitLab Runner.
Контрольный список безопасности и эксплуатацииВнутренний маршрут предназначен для служебного трафика доверенных заданий CI. Он не ослабляет политику BusinessProxy для браузерного доступа пользователей и не должен превращаться во вторую публичную точку входа GitLab.
  • Оставляйте TLS-прокси доступным только внутри сети, подключайте файлы ключей только для чтения и перезагружайте конфигурацию только после успешного выполнения nginx -t.
  • Подключайте GitLab Runner только к доверенным проектам, защищайте задания публикации и заменяйте токен аутентификации GitLab Runner при подозрении на его раскрытие.
  • Следите за сроком действия сертификата, ошибками получения заданий, сбоями при публикации и загрузке пакетов, а также за свободным местом на диске сервера.
  • Сохраняйте резервный способ административного доступа и заранее проверенную копию предыдущей конфигурации GitLab Runner.