Собственный реестр контейнеров решает три задачи: устраняет зависимость от лимитов публичных хабов, исключает утечку проприетарного кода и ускоряет выкатку в production за счет размещения образов внутри вашей сети. Вы получаете полный контроль над тем, кто и какие образы загружает, где они хранятся и как долго живут.
Это руководство проведет вас от запуска простого Docker Registry за пять минут до развертывания корпоративного Harbor с LDAP-аутентификацией и сканированием уязвимостей. Вы скопируете готовые команды, настроите SSL и получите работающий приватный реестр к концу чтения.
Краткое содержание
- Зачем нужен приватный реестр и какой выбрать
- Сравнение Docker Registry, Harbor и GitLab Container Registry
- Быстрый старт: запуск Docker Registry с SSL за 5 минут
- Harbor: корпоративный реестр с расширенной безопасностью
- GitLab Container Registry: встроенное решение для CI/CD
- Устранение типичных проблем и дальнейшая эксплуатация
Зачем нужен приватный реестр и какой выбрать
Публичные реестры вроде Docker Hub вводят rate limits на скачивание, блокируют анонимные запросы и не гарантируют конфиденциальность загруженных образов. Для команды из десяти разработчиков, активно гоняющей CI/CD пайплайны, лимит в 100 pull-запросов за шесть часов исчерпывается за утренний деплой. Приватный реестр снимает это ограничение.
Выбор решения сводится к трем вариантам: Docker Registry - минималистичный и легковесный, Harbor - платформа с корпоративной безопасностью, GitLab Container Registry - встроенный инструмент для тех, кто уже использует GitLab.
Быстрый выбор по сценарию внедрения
- dev и тестовые среды: Docker Registry, если достаточно одного узла, базовой аутентификации и ручного управления очисткой.
- small team: Docker Registry остается практичным вариантом, пока не требуются встроенные RBAC, vulnerability scanning, LDAP/OIDC и централизованные retention policy.
- enterprise: Harbor, если необходимы контроль доступа, Harbor Trivy, репликация, аудит и формализованные требования к безопасности цепочки поставки.
- GitLab-first инфраструктура: GitLab Container Registry, когда GitLab уже является основной платформой для репозиториев и CI/CD, а отдельный портал реестра не нужен.
Сравнение Docker Registry, Harbor и GitLab Container Registry
Docker Registry - это эталонная реализация от Docker, Inc. Он запускается одной командой, потребляет минимум ресурсов и поддерживает базовую аутентификацию через htpasswd. Встроенного веб-интерфейса нет, сканирования уязвимостей нет, репликации нет. Подходит для команд, которым нужно быстро поднять хранилище образов без дополнительной инфраструктуры.
Harbor - проект Cloud Native Computing Foundation с полноценным веб-интерфейсом, ролевой моделью (RBAC), интеграцией с LDAP и OIDC, автоматическим сканированием через Trivy и репликацией между дата-центрами. Требует Docker Compose и минимум 2 ГБ оперативной памяти. Выбор для организаций, где безопасность цепочки поставок зафиксирована в compliance-требованиях.
GitLab Container Registry встроен в GitLab и не требует отдельной установки. Каждый проект получает изолированное пространство имен, аутентификация работает через токены GitLab CI, очистка старых образов настраивается через политики тегов. Если GitLab уже развернут в компании, отдельный реестр не нужен.
| Функция | Docker Registry | Harbor | GitLab Container Registry |
|---|---|---|---|
| Аутентификация | htpasswd, токены | LDAP, OIDC, htpasswd | GitLab OAuth, токены CI |
| SSO/LDAP/OIDC | Через внешний token auth service | Встроенная интеграция | Через настройки GitLab |
| Сканирование уязвимостей | Нет | Trivy (встроен) | Через внешние инструменты |
| Репликация | Нет | Push/pull между инстансами | Geo (в Premium) |
| Retention и garbage collection | Внешняя автоматизация и ручной garbage collection | Tag Retention Rules и garbage collection | Cleanup policy на уровне проекта |
| Хранение | Локальный volume или object storage через storage driver | Файловое или object storage | Хранилище, настроенное в GitLab |
| Backup и restore | Конфигурация, auth и снапшот хранилища | Данные Registry, PostgreSQL и конфигурация | gitlab-backup и отдельный backup object storage |
| HA | Нет встроенной; требуются балансировщик и общее хранилище | Возможна в отдельной HA-архитектуре | Зависит от HA-архитектуры GitLab |
| Хранение Helm-чартов | Нет | Да | Через Package Registry |
| Веб-интерфейс | Нет | Полноценный портал | Встроен в GitLab |
| Установка | Одна команда docker run | Docker Compose, 5-10 минут | Активация в gitlab.rb |
| Ресурсы (мин.) | 256 МБ RAM | 2 ГБ RAM | Зависит от GitLab |
Рекомендация: для старта и небольших команд - Docker Registry, для enterprise-среды с требованиями к аудиту и безопасности - Harbor, для экосистемы GitLab - встроенный Container Registry.
Минимальные требования и эксплуатационные ограничения
Для Docker Registry 256 МБ RAM достаточно для самого сервиса, однако объем и скорость persistent storage обычно важнее памяти. В типовом запуске чаще всего возникают проблемы с DNS, SSL, правами на смонтированную директорию и очисткой удаленных тегов.
Harbor запускает несколько зависимых сервисов, включая database, redis и trivy-adapter. Указанные 2 ГБ RAM подходят как минимальная оценка для небольшого контура; перед production учитывайте параллельные сканирования, число проектов и размер хранилища. Типовые причины сбоев - несоответствие hostname сертификату, неверные пути к томам и недостаток места в data_volume.
GitLab Container Registry не требует отдельного пользовательского портала, но увеличивает требования к уже работающему GitLab, его storage и backup. На практике проверяют DNS, сертификат, registry_external_url, доступ Runner к реестру и права CI-джоб на push.
Быстрый старт: запуск Docker Registry с SSL за 5 минут
Предполагаем, что Docker установлен. Хост с IP 192.168.1.100 и доменным именем registry.example.local. DNS или файл hosts на клиентах должен разрешать это имя в IP реестра. Запускаем защищенный реестр с аутентификацией.
Генерация самоподписанного SSL-сертификата
Создаем директорию для сертификатов и генерируем ключ с сертификатом одной командой:
mkdir -p /opt/registry/certs && cd /opt/registry/certs
openssl req -newkey rsa:4096 -nodes -sha256 -keyout registry.key -x509 -days 365 -out registry.crt -subj "/CN=registry.example.local" -addext "subjectAltName=DNS:registry.example.local"Параметры: -newkey rsa:4096 - ключ RSA длиной 4096 бит, -nodes - без парольной фразы (реестр не сможет запросить пароль интерактивно), -sha256 - алгоритм подписи, -x509 - самоподписанный сертификат, -days 365 - срок действия один год. Параметр subjectAltName нужен современным Docker-клиентам: одного CN для проверки имени сертификата недостаточно.
На каждом клиенте, который будет обращаться к реестру, этот сертификат нужно добавить в доверенные. Копируем registry.crt на клиентскую машину и выполняем:
sudo cp registry.crt /usr/local/share/ca-certificates/registry.crt
sudo update-ca-certificatesДля Docker-демона надежнее дополнительно разместить CA-сертификат по пути /etc/docker/certs.d/registry.example.local:5000/ca.crt и перезапустить Docker: sudo systemctl restart docker. Без доверенного CA docker login завершится ошибкой x509: certificate signed by unknown authority.
Настройка базовой аутентификации через htpasswd
Устанавливаем утилиту для генерации htpasswd-файла и создаем первого пользователя:
sudo apt install -y apache2-utils
mkdir -p /opt/registry/auth
htpasswd -Bc /opt/registry/auth/htpasswd adminФлаг -B включает bcrypt-хеширование, -c создает новый файл (при добавлении второго пользователя флаг -c опускаем, иначе файл перезапишется).
Запускаем контейнер реестра, монтируя сертификаты, файл паролей и persistent storage:
docker run -d \
--name registry \
--restart=always \
-p 5000:5000 \
-v /opt/registry/certs:/certs \
-v /opt/registry/auth:/auth \
-v /opt/registry/data:/var/lib/registry \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_STORAGE_DELETE_ENABLED=true \
registry:2Проверяем работу: docker login registry.example.local:5000, вводим логин admin и пароль, затем пушим тестовый образ:
docker pull alpine:latest
docker tag alpine:latest registry.example.local:5000/alpine:latest
docker push registry.example.local:5000/alpine:latestОбраз загружен в приватный реестр. Дальше - настройка production-окружения с Harbor.
Production-минимум для Docker Registry
Команда выше подходит для одного узла. Для production определите единую точку завершения TLS: либо непосредственно в Registry, как в примере, либо на reverse proxy. Reverse proxy также используют для лимитов, логирования и единообразной публикации реестра по HTTPS.
htpasswd не заменяет LDAP/OIDC. Для централизованной аутентификации Docker Registry потребуется внешний token auth service; если он нужен вместе с RBAC и аудитом, обычно практичнее использовать Harbor. Директория /opt/registry/data должна находиться на persistent storage и входить в backup вместе с /opt/registry/auth, сертификатами и конфигурацией.
У Docker Registry нет встроенных retention policy и отказоустойчивости. Для удаления устаревших тегов требуется внешняя автоматизация, а HA-архитектура требует балансировщика и общего совместимого storage backend. Локальный volume из примера нельзя просто подключить к нескольким репликам без отдельного проектирования хранилища.
Когда Docker Registry не подходит
Не выбирайте Docker Registry как конечное решение, если нужны встроенные vulnerability scanning, LDAP/OIDC, веб-интерфейс, репликация между площадками, детальные RBAC или централизованные политики хранения. В этих сценариях затраты на внешние компоненты обычно превышают выгоду от минимальной установки.
Harbor: корпоративный реестр с расширенной безопасностью
Harbor устанавливается через официальный инсталлятор, который поставляется с Docker Compose-файлом и набором контейнеров: core, portal, jobservice, registry, database, redis, trivy-adapter. Перед установкой в production сверяйте выбранную версию Harbor с требованиями вашей инфраструктуры. В примере используется следующая версия:
wget https://github.com/goharbor/harbor/releases/download/v2.12.0/harbor-online-installer-v2.12.0.tgz
tar xzvf harbor-online-installer-v2.12.0.tgz
cd harbor
cp harbor.yml.tmpl harbor.ymlРедактируем harbor.yml: указываем hostname: registry.example.local, пути к SSL-сертификатам (можно использовать сгенерированные ранее или указать путь к сертификату Let's Encrypt), пароли администратора и базы данных. Запускаем установку:
sudo ./install.sh --with-trivyФлаг --with-trivy включает сканер уязвимостей. После выполнения скрипта Harbor доступен по HTTPS на порту 443. Логин в веб-интерфейс: admin / пароль из harbor.yml.
Что обязательно проверить в harbor.yml и после установки
Минимально проверьте hostname, блок https с путями к certificate и private_key, harbor_admin_password, пароль database и data_volume. Имя в hostname должно совпадать с DNS-именем, по которому клиенты обращаются к Harbor, и с именем в SSL-сертификате.
Не оставляйте пароли из шаблона и не размещайте data_volume на временном диске. После установки войдите под admin, создайте тестовый проект, настройте RBAC, выполните docker login, push и pull тестового образа. При включенном Trivy также убедитесь, что сканирование запускается и результат появляется в проекте.
Интеграция Harbor с LDAP и OIDC
Централизованная аутентификация настраивается в разделе Administration / Configuration / Authentication. Для Active Directory заполняем поля:
Auth Mode: ldap
LDAP URL: ldaps://ad.example.local:636
LDAP Search DN: cn=admin,dc=example,dc=local
LDAP Search Password: <пароль>
LDAP Base DN: dc=example,dc=local
LDAP UID: sAMAccountNameНажимаем «Test LDAP Server» - Harbor проверит подключение и покажет список найденных пользователей. Перед сохранением проверьте доступ Harbor к LDAP URL, доверие к CA контроллера домена и корректность Search DN. После сохранения любой сотрудник домена входит в Harbor под своей учетной записью AD.
Для OIDC (Keycloak, Okta, Azure AD) указываем:
Auth Mode: oidc
OIDC Provider Name: Keycloak
OIDC Endpoint: https://keycloak.example.local/realms/harbor
OIDC Client ID: harbor
OIDC Client Secret: <секрет>
OIDC Scope: openid,profile,email
Verify Certificate: onПосле сохранения на странице логина появляется кнопка «Login via Keycloak». Пользователи перенаправляются на форму провайдера, а после аутентификации возвращаются в Harbor с назначенной ролью. Проверьте, что redirect URL в OIDC-провайдере соответствует внешнему HTTPS-адресу Harbor.
Сканирование уязвимостей и подпись образов
Trivy в составе Harbor автоматически сканирует каждый запушенный образ. Результат виден на вкладке образа: перечень CVE с уровнями критичности. Настройка политик блокировки находится в Projects / Configuration / Policy: включаем «Prevent vulnerable images from running» и задаем порог, например, блокировать образы с Critical-уязвимостями.
Harbor поддерживает подпись образов через Notary. Для включения добавляем в harbor.yml блок notary и перезапускаем инсталлятор. После этого в настройках проекта активируется опция «Content Trust» - клиенты обязаны подписывать образы перед пушем, а Harbor проверяет подпись при приеме.
Если нужна миграция существующих образов из другого реестра, используйте пошаговое руководство по переносу Docker-образов между реестрами с проверкой целостности через digest.
Когда Harbor не подходит
Harbor избыточен для краткоживущей dev-среды на одном хосте, если команде нужен только защищенный push/pull и она не готова сопровождать дополнительные сервисы, storage, backup и обновления. В GitLab-first инфраструктуре без отдельных требований к репликации и сканированию также может быть достаточно GitLab Container Registry.
GitLab Container Registry: встроенное решение для CI/CD
Если GitLab уже обслуживает репозитории кода, его Container Registry активируется одной строкой в /etc/gitlab/gitlab.rb:
registry_external_url 'https://registry.example.local'После sudo gitlab-ctl reconfigure реестр доступен по указанному домену. Для Let's Encrypt необходимы публично разрешаемое доменное имя и доступность портов 80 и 443. Во внутренней сети используйте сертификат корпоративного CA или разместите готовые сертификаты в /etc/gitlab/ssl/ с именами registry.example.local.crt и registry.example.local.key.
Каждый GitLab-проект получает изолированное пространство имен: registry.example.local/group/project. Права на push определяются ролью пользователя и настройками проекта: для push обычно требуется Developer или выше. Права на pull также зависят от видимости проекта, поэтому их следует проверить отдельной учетной записью до подключения production-клиентов.
Настройка GitLab CI для автоматической публикации образов
Пример ниже собирает образ и публикует его в GitLab Container Registry в одной CI-джобе. Он рассчитан на Docker Runner, которому разрешен Docker-in-Docker: для такого Runner нужен privileged-режим и общий том /certs/client для TLS-соединения с сервисом Docker.
stages:
- build
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
build_and_push:
stage: build
image: docker:26
services:
- name: docker:26-dind
before_script:
- docker login --username "$CI_REGISTRY_USER" --password "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
script:
- docker build --pull -t "$IMAGE_TAG" .
- docker push "$IMAGE_TAG"
- docker tag "$IMAGE_TAG" "$CI_REGISTRY_IMAGE:latest"
- docker push "$CI_REGISTRY_IMAGE:latest"Переменные $CI_REGISTRY_USER, $CI_REGISTRY_PASSWORD, $CI_REGISTRY и $CI_REGISTRY_IMAGE GitLab предоставляет автоматически для CI-джобы текущего проекта. Никаких секретов в коде: токен CI-джобы уже имеет права на push в реестр проекта.
Для push в реестр другого проекта одних стандартных переменных недостаточно: настройте разрешения CI_JOB_TOKEN между проектами либо используйте deploy token с правом write_registry. Также проверьте, что защищенный Runner запускает джобы для ветки или тега, из которых разрешена публикация образов.
Очистка старых образов настраивается в Settings / Packages and Registries / Cleanup policy. Правило: удалять образы старше 30 дней, оставлять минимум 5 последних тегов. GitLab запускает очистку раз в сутки.
Для интеграции с внешними CI/CD системами пригодится руководство по интеграции реестра с Jenkins, GitLab CI и GitHub Actions - там готовые конфигурации для всех трех платформ.
Когда GitLab Container Registry не подходит
Отдельный GitLab Container Registry не является лучшим выбором, если GitLab в компании отсутствует, реестр должен обслуживать независимые команды и платформы или требуется отдельная HA-архитектура с репликацией между площадками. При обязательном встроенном vulnerability scanning и расширенных политиках безопасности разумнее оценить Harbor.
Устранение типичных проблем и дальнейшая эксплуатация
Самые частые ошибки при развертывании связаны с сертификатами и аутентификацией. Разберем их и способы решения.
Ошибки сертификатов и как их избежать
x509: certificate signed by unknown authority. Docker-демон не доверяет сертификату реестра. Решение: скопировать CA-сертификат в /etc/docker/certs.d/registry.example.local:5000/ca.crt на клиенте и перезапустить демон. Для Harbor и GitLab Registry путь аналогичен, порт указывается только если он нестандартный.
Для тестовых сред можно добавить реестр в insecure-registries в /etc/docker/daemon.json, но так делать в production нельзя - трафик пойдет без шифрования.
Альтернатива самоподписанным сертификатам - Let's Encrypt. Для Harbor сертификат обычно получают отдельным ACME-клиентом или на reverse proxy, затем указывают его пути в harbor.yml. Для GitLab автоматическое получение сертификата также требует корректно настроенного публичного DNS и доступных портов.
Очистка неиспользуемых образов и управление хранилищем
Реестр без очистки растет неограниченно. Каждый новый билд с уникальным тегом добавляет слой, и через месяц активной разработки хранилище может занять сотни гигабайт.
Для Docker Registry сначала удаляют ненужные манифесты через API или внешнюю задачу очистки, затем запускают garbage collection:
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.ymlGarbage collection удаляет неиспользуемые blobs, но сам по себе не является retention policy. Переменная REGISTRY_STORAGE_DELETE_ENABLED=true в команде запуска разрешает удаление манифестов. Выполняйте garbage collection в окно обслуживания: во время операции реестр должен быть read-only или не принимать записи. Не удаляйте файлы из storage вручную.
Harbor управляет очисткой через политики хранения: Projects / Configuration / Tag Retention Rules. Правило «keep the most recent 10 images» оставляет 10 последних версий и удаляет остальные. Garbage collection запускается по расписанию в Administration / Garbage Collection.
GitLab Container Registry использует cleanup policy в настройках проекта. Политика срабатывает раз в сутки и удаляет теги, подпадающие под правило (например, все теги кроме latest и release-* старше 14 дней).
Для production-сред важно настроить мониторинг свободного места. Harbor предоставляет метрики Prometheus на /metrics, Docker Registry - через отдельный экспортер. Настройте алерт на заполнение диска более 80%. При использовании object storage дополнительно контролируйте квоты, ошибки доступа и доступность bucket.
Безопасность реестра не заканчивается на SSL и аутентификации. Рекомендую изучить стратегии защиты реестра от уязвимостей - там детально разобраны RBAC, шифрование хранилища и политики допуска в Kubernetes. Для комплексной защиты контейнеров на всех этапах пригодится чек-лист безопасности Docker-контейнеров 2026 с готовыми командами.
Резервное копирование реестра - это не только копирование данных, но и проверка возможности восстановить их с конфигурацией и правами доступа. Для Docker Registry сохраняйте /var/lib/registry, htpasswd, сертификаты и параметры запуска. Для Harbor необходимы данные Registry, база данных PostgreSQL и конфигурация. Для GitLab используйте штатный механизм gitlab-backup, а при хранении Registry в object storage отдельно создавайте backup bucket. Перед внедрением проверьте восстановление в изолированной среде.