UMGUM.COM (лучше) 

GitLab Container Registry ( Активация встроенного в "GitLab" репозитория docker-образов "Container Registry" с проверкой его функциональности. )

3 апреля 2020  (обновлено 4 мая 2021)

OS: "Linux Debian 9/10", "Linux Ubuntu Server 16/18/20 LTS".
Apps: "GitLab CE/EE", "GitLab Container Registry".

Задача: активировать встроенный в комбайн "GitLab" репозиторий docker-образов "GitLab Container Registry" с последующей проверкой функциональности. Примем за данность, что "GitLab" уже установлен по вышестоящей инструкции.

Дальнейшие действия:

1. Активация и настройка "GitLab Container Registry";
2. Проверка функциональности "GitLab Container Registry";
3. Автоматизация очистки от ненужных данных в "Container Registry".


Активация и настройка "GitLab Container Registry".

По умолчанию подсистема "GitLab Container Registry" (базирующаяся на "Docker Registry") отключена. Она активируется, полностью автоматически настраиваясь оркестратором "Omnibus", при обнаружении в конфигурационном файле параметра "registry_external_url":

# vi /etc/gitlab/gitlab.rb

....
# URL, на котором обслуживаются запросы к "GitLab" (настроен ранее)
external_url 'https://gitlab.example.net'

# Указываем URL, на котором обслуживаются запросы к "GitLab Container Registry"
registry_external_url 'https://gitlab.example.net:5000'

# Переводим встроенный сервер "Docker Registry" на свободный порт "локальной петли"
registry['registry_http_addr'] = "localhost:5001"
....

По умолчанию интегрированный в "GitLab" сервер "Docker Registry" запускается на локальной сетевой петле, принимая проксируемые от "GitLab" запросы на выделенном порту TCP:5000, что вынуждает для приёма подключений извне выбирать другой порт. Это весьма неудобно, так как заставляет пользователей вносить изменения к конфигурации своих приложений, по умолчанию работающих через порт TCP:5000, выделенный для сервиса "Docker Registry". В конфигурации выше мы переводим встроенный сервер "Docker Registry" на произвольный свободный порт, а высвободившийся TCP:5000 задействуем для приёма клиентских подключений извне.

В параметре "registry_external_url" три ключевых части. Указание протокола "https" по сути обязательно, так как это требование подкапотного "Docker Registry" - таковой не осуществляет аутентификацию по незащищённому каналу (чтобы не допустить утечки паролей). FQDN может быть произвольным - блок обслуживания адресованных ему запросов автоматически будет добавлен в конфигурацию встроенного в "GitLab" web-сервера "Nginx". TCP-порт может быть произвольным, за исключением уже используемых.

Важно иметь в виду, что "external_url" (адрес "GitLab") и "registry_external_url" (адрес "GitLab Container Registry") должны отличаться, иначе внутренний маршрутизатор межкомпонентных запросов не поймёт, куда направлять потоки данных. Если использовать одинаковые FQDN, то в запросах клиентов к "Docker Registry" придётся явно указывать TCP-порт.

На практике в "GitLab" приходится пользоваться единым FQDN для всех его компонентов потому, что автоматически запрашиваются только SSL-сертификаты "Let`s Encrypt" для FQDN основного сервиса "GitLab" (так в моих инсталляциях, в основном 12.x). При желании можно указать использовать для "GitLab Container Registry" имеющийся выделенный сертификат, но впоследствии предстоит ежегодная возня с его обновлением, что может быть неудобным:

....
# (опционально) Явно указываем используемые для FQDN "реестра" SSL-сертификаты
registry_nginx['ssl_certificate'] = "/etc/ssl/gitlab/registry.example.net.crt"
registry_nginx['ssl_certificate_key'] = "/etc/ssl/gitlab/registry.example.net.key"
....

Применяем изменения:

# gitlab-ctl reconfigure

Проверяем, правильным ли сертификатом отвечает "GitLab Container Registry":

$ echo QUIT | openssl s_client -connect gitlab.example.net:5000 | openssl x509 -noout -text | less

Проверка функциональности "GitLab Container Registry".

Для использования реестра docker-образов в "GitLab" требуется предварительная аутентификация. Учитывая то, что клиенты "Docker Registry" не обеспечивают безопасное хранение паролей, для этого сервиса выделяется отдельный набор логинов и паролей, названых здесь "токенами". У каждого пользователя может быть несколько "токенов", предъявителям которых он разрешает ограниченный доступ к тем или иным подсистемам. Каждый "токен" по отдельности можно легко отозвать (так же и автоматически, по истечению срока действия), не блокируя при этом основную учётную запись.

Итак, создаём "токен" и выделяем его для доступа к "GitLab Container Registry":

URL: https://gitlab.example.net/profile/personal_access_tokens
User Settings -> Access Tokens:
  Add a personal access token:
    Name: gitlab-token-username
    Scopes: api, read_registry

Подключаясь к "Docker Registry" можно указывать URL как полностью детально, так и подразумевая дополнение его "по умолчанию". Аккуратность призывает к первому, но практика подсказывает, что лучше покороче, так как указанный URL в дальнейшем будет фигурировать в качестве "имени репозитория":

$ docker login -u gitlab-token-username gitlab.example.net:5000

Как я упоминал выше, логин и пароль для подключения к "Docker Registry" по умолчанию сохраняются в открытом виде (закодированы "Base64") в домашней директории docker-клиента - поэтому мы используем "токены" вместо учётных записей пользователей "GitLab":

$ cat ~/.docker/config.json

{
  "auths": {
    "gitlab.example.net": {
    "auth": "cm9...eg=="
  }
....
}

После того, как мы убедились, что подключение к "Docker Registry" осуществимо, подготовим docker-образы для загрузки в реестр.

Принцип определения, какие конкретно "образы" выгружать в реестр, построен на тегировании. Если в "теге" docker-образа указан репозиторий, к которому налажено подключение, то по команде выгрузки он будет туда отправлен.

Таким образом, при создании "образа" мы просто указываем, в каком репозитории он должен быть размещён, и в процессе сборки он будет туда залит:

$ docker build --tag gitlab.example.net:5000/group/project:app-1.234 --file ./Dockerfile .

Как вариант, можно добавить "тег" к уже имеющемуся образу, указывая тем самым, что он должен быть размещён ещё и в нужном нам репозитории.

Запрашиваем перечень локальных "образов":

$ docker images

REPOSITORY TAG       IMAGE ID
selfmade   app-1.234 8dfd976a2acf

Добавляем "тег" с указанием целевого репозитория к имеющемуся docker-образу:

$ docker tag 8dfd976a2acf gitlab.example.net:5000/group/project:app-1.234

Теперь один и тот же "образ" отмечен, как размещаемый в локальном и удалённом хранилищах:

$ docker images

REPOSITORY                            TAG       IMAGE ID
selfmade                              app-1.234 8dfd976a2acf
gitlab.example.net:5000/group/project app-1.234 8dfd976a2acf

Даём команду отправить в "Docker Registry" изменения "образов", имеющие отношение к целевому репозиторию:

$ docker push gitlab.example.net:5000/group/project

The push refers to repository [gitlab.example.net/group/project]
690...27: Pushed
627...4c: Pushed
app-1.234: digest: sha256:879...1c size: 741

Обратимся непосредственно к репозиторию, запросим перечень его docker-образов - наш должен быть там:

$ docker images -a gitlab.example.net:5000/group/project

REPOSITORY                            TAG       IMAGE ID
gitlab.example.net:5000/group/project app-1.234 8dfd976a2acf

Ненужный или неверный "тег" при docker-образе в локальном хранилище легко удалить:

$ docker rmi selfmade:app-1.234

Бесплатные версии docker-клиентов не поддерживают простое прямое удаление docker-образов из удалённого репозитория - это приходится делать через специальное REST-API, специфичное для каждого продукта, будь то "GitLab", "Nexus" или оригинальный "Docker Registry" - мы рассмотрим эту методику позже.

Проще всего неподготовленному пользователю удалить ненужный ему образ через web-интерфейс "GitLab":

GitLab -> Project -> Packages -> Container Registry.

После завершения работы с "Docker Registry" желательно явно отключиться от него (с автоматическим удалением логина и пароля из файла "~/.docker/config.json" в профиле пользователя):

$ docker logout

Автоматизация очистки от ненужных данных в "GitLab Container Registry".

Важно иметь в виду, что удаление docker-образов из репозитория "GitLab Container Registry" на самом деле является не в полном смысле удалением данных, а представляет собой лишь удаление описаний docker-образов и ссылок на слои данных, при этом последние остаются в файловой системе. Не уверен, что понимаю, зачем так сделано - возможно ради скорости работы или для надёжности. Как бы то ни было, для удаления осиротевших слоёв данных (без мета-описаний) приходится регулярно запускать уборщика мусора:

# vi /etc/crontab

....
# Weekly garbage collection in "GitLab Container Registry"
1 4 * * 0  root gitlab-ctl registry-garbage-collect -m

Проблемы: подключение к серверу с "самоподписанным" SSL-сертификатом.

В случае, если "GitLab Container Registry" работает через "сампоподписанный (self-signed)" SSL-сертификат, подключающийся docker-клиент не сможет проверить его подлинность и откажется работать со следующим сообщением:

Error response from daemon: Get https://gitlab.example.net:5000/v2/: x509: certificate signed by unknown authority

Для обхода проблемы придётся явно подать "Docker"-у публичную часть сертификата целевого сервера как доверенную, разместив его в предназначенном для этого месте файловой системы (последняя директория в иерархии должна точно соответствовать FQDN целевого сервера, включая порт, если таковой указывается - например: "gitlab.example.net:5000"):

# mkdir -p /etc/docker/certs.d/gitlab.example.net:5000
# cp ./gitlab.example.net-ss.crt /etc/docker/certs.d/gitlab.example.net:5000/


Заметки и комментарии к публикации:


Оставьте свой комментарий ( выразите мнение относительно публикации, поделитесь дополнительными сведениями или укажите на ошибку )