в bash, docker, GitLab, scripts

Gitlab + Gitlab CI + Docker registry с помощью docker-compose


В одной из предыдущих статей мы подробно рассматривали процесс переноса данных omnibus-установки в docker-установку, целью которого было избавление от головной боли при обновлениях Gitlab.

В результате у нас получался «монолитный» docker-контейнер с redis + postgres + Gitlab в одном флаконе. Давайте разберемся, как разделить этот монолит по нескольким контейнерам и заодно серьезно расширить функциональность, добавив в установку приватный docker-registry и фундамент для Gitlab CI!

Считаем, что у нас уже установлен docker-engine. Установить docker-compose довольно несложно:

sudo curl -L https://github.com/docker/compose/releases/download/1.11.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

Сделаем резервную копию данных актуальной версии Gitlab, которую мы запускали в docker-контейнере с именем gitlab:

sudo docker exec -it gitlab gitlab-rake gitlab:backup:create

После успешного выполнения команды в каталоге /srv/gitlab/data/backups на хост-машине появится бекап (например, с именем 1487683641_2017_03_03_gitlab_backup.tar).

Удаляем контейнер с установленным Gitlab, с которым работали ранее — теперь он нам больше не понадобится:

sudo docker rm -f gitlab

В дальнейшем работаем с утилитой docker-compose. Создадим каталог для проекта и перейдем в него:

sudo mkdir -p /opt/gitlab-with-registry && cd /opt/gitlab-with-registry

В каталоге проекта создаем конфигурационный файл docker-compose.yml следующего содержания:

version: '2'
services:
  redis:
    container_name: gitlab-redis
    restart: always
    image: sameersbn/redis:latest
    command:
    - --loglevel warning
    volumes:
    - /srv/redis:/var/lib/redis:Z
    networks:
    - mynet

  postgresql:
    container_name: gitlab-postgres
    restart: always
    image: sameersbn/postgresql:9.6-1
    volumes:
    - /srv/postgresql:/var/lib/postgresql:Z
    environment:
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production
    - DB_EXTENSION=pg_trgm
    networks:
    - mynet

  gitlab:
    container_name: gitlab
    restart: always
    image: sameersbn/gitlab:8.17.2
    depends_on:
    - redis
    - postgresql
    ports:
    - "10080:80"
    - "10022:22"
    volumes:
    - /srv/gitlab/data:/home/git/data:Z
    - /srv/gitlab/logs:/var/log/gitlab
    - /srv/certs:/certs
    environment:
    - DEBUG=false

    - DB_ADAPTER=postgresql
    - DB_HOST=postgresql
    - DB_PORT=5432
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production

    - REDIS_HOST=redis
    - REDIS_PORT=6379
    - GITLAB_SSH_PORT=10022
    - GITLAB_PORT=10080
    - GITLAB_HOST=git.labs.lc

    - GITLAB_SECRETS_SECRET_KEY_BASE=neraterandomstringstasdasdghjfkajfhsakjfhk234hkwdjhfdskjfhsdkjf
    - GITLAB_SECRETS_OTP_KEY_BASE=dfjdsafjsaglhjsdlkfjghsldfghjdslfjghsldfghjsldjfhgsldkjfhglsjdfghdslfghjldsjfhgdsljfghdsljfghsldjfghdsljghf
    - GITLAB_SECRETS_DB_KEY_BASE=superrandomsecret

    - GITLAB_REGISTRY_ENABLED=true
    - GITLAB_REGISTRY_HOST=registry.git.labs.lc
    - GITLAB_REGISTRY_PORT=5000
    - GITLAB_REGISTRY_API_URL="https://registry.git.labs.lc:5000/"
    - GITLAB_REGISTRY_KEY_PATH=/certs/registry-auth.key
    - SSL_REGISTRY_CERT_PATH=/certs/registry.crt
    - SSL_REGISTRY_KEY_PATH=/certs/registry.key
    networks:
     mynet:
      aliases:
      - git.labs.lc

  registry:
    container_name: docker-registry
    restart: always
    image: registry:2.4.1
    volumes:
    - /srv/gitlab/shared/registry:/registry
    - /srv/certs:/certs
    environment:
    - REGISTRY_LOG_LEVEL=info
    - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/registry
    - REGISTRY_AUTH_TOKEN_REALM=http://git.labs.lc:10080/jwt/auth
    - REGISTRY_AUTH_TOKEN_SERVICE=container_registry
    - REGISTRY_AUTH_TOKEN_ISSUER=gitlab-issuer
    - REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/certs/registry-auth.crt
    - REGISTRY_STORAGE_DELETE_ENABLED=true
    - REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt
    - REGISTRY_HTTP_TLS_KEY=/certs/registry.key
    ports:
    - "0.0.0.0:5000:5000"
    networks:
     mynet:
      aliases:
      - registry.git.labs.lc

  gitlab-runner:
   container_name: gitlab-runner
   image: gitlab/gitlab-runner:latest
   volumes:
     - /srv/gitlab-runner/data:/home/gitlab_ci_multi_runner/data
     - /srv/gitlab-runner/config:/etc/gitlab-runner
     - /var/run/docker.sock:/var/run/docker.sock:rw
   environment:
     - CI_SERVER_URL=http://git.labs.lc:10080/ci
   restart: always
   dns: 192.168.0.1

networks:
  mynet:

Согласно данному файлу, будут запущены пять docker-контейнеров (gitlab-redis, gitlab-postgres, gitlab, docker-registry и gitlab-runner). Именно два последних контейнера из списка и позволят нам расширить функциональность обычной установки Gitlab — docker-registry это приватный репозиторий для docker-образов, а gitlab-runner — важнейшее звено Gitlab CI (Gitlab Continuous Integration), которую мы будем использовать в будущем.

Находясь в каталоге проекта запускаем все контейнеры с помощью docker-compose, чтобы создались необходимые каталоги, после чего останавливаем контейнеры:

sudo docker-compose -f docker-compose.yml up -d && sudo docker-compose stop

При запуске контейнеров будет создан каталог /srv/docker/gitlab/gitlab на хост машине, внутри которого будет находиться папка backups — перекладываем в нее созданный ранее бекап после чего восстанавливаем данные командой:

sudo docker-compose run --rm gitlab app:rake gitlab:backup:restore BACKUP=1487683641_2017_03_03

Запускаем всю связку, описанную в конфигурационном файле docker-compose.yml:

sudo docker-compose -f docker-compose.yml up -d

Для всех старых проектов необходимо вручную включить Registry (на странице проекта «Settings -> Edit Project», чекбокс «Container Registry»), для новых же проектов этот компонент будет включаться по умолчанию.

Для корректной работы Registry необходимо сгенерить самоподписанные сертификаты (или использовать бесплатные от Let’s Encrypt), для этого переходим в каталог /srv/certs:

cd /srv/certs

Создаем скрипт make_certs.sh (не забываем сделать его исполняемым) следующего содержания:

#/bin/bash

#####echo "Create Signing Key and CSR"
openssl req -nodes -newkey rsa:2048 -keyout registry-auth.key -out registry-auth.csr -subj "/CN=git.labs.lc"
#####echo "Self-Sign Certificate"
openssl x509 -in registry-auth.csr -out registry-auth.crt -req -signkey registry-auth.key -days 3650

openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.pem
openssl genrsa -out registry.key 2048
openssl req -new -key registry.key -out registry.csr
###### Common Name
####Common Name (eg, YOUR name) []: registry.git.labs.lc
openssl x509 -req -in registry.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out registry.crt -days 500

Примечание. В процессе генерации сертификатов обязательно в Common Name указываем имя домена, на котором будет висеть реестр, например: Common Name (eg, YOUR name) []: registry.git.labs.lc.

Для доступа к странице Registry из браузера необходимо подключиться к контейнеру с Gitlab:

sudo docker exec -it gitlab bash

и выполнить следующие команды:

cp /certs/* /usr/local/share/ca-certificates/
update-ca-certificates --fresh

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

    • Была проблема с подключением раннера к гитлабу, сначала решалась добавлением dns: 192.168.0.1, сейчас же описание сервиса gitlab-runner выглядит так:

      gitlab-runner:
      container_name: gitlab-runner
      image: gitlab/gitlab-runner:latest
      volumes:
      - /srv/gitlab-runner2/data:/home/gitlab_ci_multi_runner/data
      - /srv/gitlab-runner2/config:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock:rw
      environment:
      - CI_SERVER_URL=http://gitlab.lc:10087/ci
      restart: always
      extra_hosts:
      - "gitlab.lc:192.168.0.218"
      - "registry.gitlab.lc:192.168.0.218"

  1. Добрый день. С такой конфигурацией docker-compose, gitlab-runner не сможет подключиться к gitlab’у, т.к. контейнер gitlab-runner находится в сети default, а остальные контейнеры в сети mynet. В секцию gitlab-runner нужно добавить кусочек networks: — mynet, как по мне.

  2. Добрый день. У меня контейнер docker-registry рестартует и не запускается если эти параметры активны:

    — REGISTRY_AUTH_TOKEN_REALM=http://git.mydomain.com:10080/jwt/auth
    — REGISTRY_AUTH_TOKEN_SERVICE=container_registry
    — REGISTRY_AUTH_TOKEN_ISSUER=gitlab-issuer
    — REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/certs/registry-auth.crt
    — REGISTRY_STORAGE_DELETE_ENABLED=true
    — REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt
    — REGISTRY_HTTP_TLS_KEY=/certs/registry.key

    Если их закоментировать, всё работает кроме ссылки Registry в самом Gitlab’e.
    При переходе по ссылке Registry получаю:

    500
    Whoops, something went wrong on our end.
    Try refreshing the page, or going back and attempting the action again.
    Please contact your GitLab administrator if this problem persists.

    Сделал всё как у вас в посте. Есть идеи, в чём я промахнулся?

    Хост OC: debian 8.8

    docker —version
    Docker version 17.03.1-ce, build c6d412e

    docker-compose —version
    docker-compose version 1.12.0, build b31ff33

    • Здравствуйте, Олег!
      С большой долей вероятности, проблема с сертификатами — сам сталкивался ))

      Вы сертификаты сгенерировали? Создавали их для «правильного» имени домена? Они попали внутрь контейнера?

      Еще можно посмотреть логи, командой

      docker logs docker-registry
    • И еще, как вариант, выполните на хост-машине команды добавления сертификатов:

      cp /certs/* /usr/local/share/ca-certificates/
      update-ca-certificates --fresh

      В будущем, на каждом компьютере, который будет подключаться к вашему локальному docker registry из консоли (для скачивания/загрузки образов), необходимо корневой сертификат (в данном примере rootCA.pem) положить в каталог

      /etc/docker/certs.d/< FQDN_ИМЯ_РЕДЖИСТРИ >:5000/

      и перезапустить сервис docker