Хорошо настроенный приватный Docker Registry в компании — это не просто место, где «лежат образы», а полноценный инфраструктурный сервис: с продуманным неймингом, предсказуемыми namespace, политиками очистки и обязательным SSL. Без этого реестр быстро превращается в свалку тегов, где страшно что-либо удалять и невозможно что-либо найти.
Ниже разберём практический подход к организации реестра для DevOps-команд: как проектировать структуру namespace, какие правила нейминга ввести, как подойти к политике тегов и retention, и почему не стоит откладывать SSL «на потом».
Базовая модель: что такое Docker Registry в корпоративном контексте
В одиночном pet-проекте реестр — это часто просто один хост и несколько образов. В компании всё иначе: десятки сервисов, несколько окружений, разные команды, внешние подрядчики, compliance‑требования.
Практически всегда возникает потребность решить сразу несколько задач:
- Разделить образы по командам и продуктам (namespace, проекты).
- Развести окружения: dev, stage, prod, sandbox.
- Обеспечить контроль доступа: кто может пушить/пуллить что и куда.
- Ввести предсказуемые правила тегов и политики хранения.
- Обеспечить безопасный доступ по HTTPS с корректным SSL.
Чем раньше вы формализуете правила, тем меньше техдолга накопится. Менять схему именования через год эксплуатации с сотнями образов — болезненно.
Нейминг и пространства имён: с чего начинать
Первый ключевой вопрос — как вы будете называть образы и namespace. Здесь важно не только удобство для людей, но и технические ограничения: длина имени, допустимые символы, совместимость с CI/CD и сторонними инструментами.
Компоненты полного имени образа
Полное имя образа в Docker выглядит так:
registry.example.com/team/project/service:tag
Смысловая разбивка обычно такая:
registry.example.com— адрес реестра (с DNS и SSL).team— команда или бизнес‑направление.project— продукт или крупный домен системы.service— конкретный сервис/микросервис.tag— версия/окружение/метаданные сборки.
Не обязательно использовать все уровни, но чёткая иерархия сильно упрощает навигацию и разграничение прав.
Основные принципы нейминга для Registry
Хорошая схема именования должна удовлетворять нескольким критериям:
- Однозначность: по имени понятно, к какому проекту, окружению и типу сервиса относится образ.
- Стабильность: схема не меняется каждые полгода, максимум — эволюционирует назад‑совместимо.
- Машинная обработка: имена легко парсятся в CI/CD скриптах (минимум спецсимволов, предсказуемый формат).
- Краткость: не уходить в чрезмерно длинные цепочки типа
corp-enterprise-b2b-accounts-frontend-nginx, иначе devops начнут хитрить и сокращать «как попало».
Пример иерархии namespace для средней компании
Один из удачных практических вариантов:
registry.corp.local/<org>/<team>/<project>/<service>:<tag>
Где:
<org>— укрупнённый блок (например,internal,external,experiments).<team>— короткий код команды (pay,core,ml).<project>— продукт (billing,lk).<service>— конкретный сервис (api,worker,frontend).
Пример реального имени:
registry.corp.local/internal/pay/billing/api:1.7.3
Такая структура хорошо сочетается с RBAC: можно дать роли на уровне org, team или project, не залезая в конкретные сервисы.
Где закодировать окружение: namespace vs tag
Один из частых споров: указывать окружение в namespace или в теге.
- Схема 1: окружение в namespace
registry.corp.local/internal/pay/billing/stage/api:1.7.3 registry.corp.local/internal/pay/billing/prod/api:1.7.3 - Схема 2: окружение в теге
registry.corp.local/internal/pay/billing/api:1.7.3-stage registry.corp.local/internal/pay/billing/api:1.7.3-prod
С практической точки зрения в большинстве случаев удобнее выносить окружение в тег. Тогда один и тот же образ (по содержимому) может использоваться в разных окружениях, если это допустимо по процессам.
Пример:
registry.corp.local/internal/pay/billing/api:1.7.3
registry.corp.local/internal/pay/billing/api:1.7.3-stage
registry.corp.local/internal/pay/billing/api:1.7.3-prod
Здесь 1.7.3 — «чистая» версия, а -stage/-prod — релейблы для конкретного окружения, которые деплой‑система может перекидывать, не пересобирая образ.
Политики тегов (tagging policies): не только latest
Если оставить разработчиков самим придумывать теги, вы почти гарантированно получите хаос: vasya-fix2, new, before-refactor и десятки вариаций latest. Важно с самого начала ввести формальные правила.
Какие теги нужны в CI/CD
Минимальный набор тегов, который комфортен для большинства пайплайнов:
- Иммутабельный тег по commit SHA:
:git-abcdef12. - Версионный тег (семантическая версия или build number):
:1.7.3или:2025.02.17-1234. - Окруженческий тег:
:stage,:prod, иногда с версией (:1.7.3-prod). - Опционально — branch tags для feature‑веток, если принято катать стенды от веток:
:feature-SOME-123.
Типичный алгоритм в CI:
- Собираем образ по commit SHA и пушим с тегом
:git-abcdef12. - Если это merge в
main, дополнительно помечаем образ тегом версии (:1.7.3). - Деплой на stage/prod делает не новую сборку, а ретеггинг уже собранного образа.
Так вы всегда можете однозначно отследить, какой код сейчас крутится в проде и откатиться к нужному SHA.
Почему опасно полагаться на latest
Использование latest как основного тега — классическая анти‑практика в проде. Основные проблемы:
- Невозможно воспроизвести конкретный релиз:
latestуже переписан. - Поведение среды зависит от момента деплоя (какой
latestбыл на тот момент). - Сложно отлаживать инциденты и проводить RCA.
Хорошее правило: latest допустим только в локальной разработке и, возможно, на dev‑окружении. В stage/prod — только иммутабельные теги.
Если нужен «человеческий» ярлык последнего стабильного релиза, используйте отдельный тег вроде :stable, но относитесь к нему как к двигающемуся «указателю» поверх иммутабельных тегов.
Политики хранения и очистки (retention policies)
Docker Registry по умолчанию не умеет автоматически удалять старые образы «по уму»: без политик диски довольно быстро забиваются, особенно если активно тегировать по SHA и хранить много feature‑сборок.
Задача DevOps — согласовать с командами реалистичные правила хранения и зашить их в автоматизацию.
Что обычно хочется хранить дольше
- Образы, которые когда‑либо были в prod (по тегам
:prod,:stable, релизным версиям). - Релизы за последние N месяцев: для быстрой диагностики и откатов.
- Тестовые сборки за короткий период (недели), если есть потребность разбирать инциденты в QA/dev.
При этом feature‑сборки и короткоживущие теги вполне можно удалять агрессивно, особенно если их десятки в день.
Примеры политик retention
Примеры, которые часто работают «из коробки» для среднего проекта:
- Prod‑релизы (теги
*-prod,stable): хранить не менее 6–12 месяцев. - Stage/dev теги: хранить 30–60 дней.
- Feature‑ветки (
feature-*): хранить 14 дней после последнего обновления. - Чистые SHA‑теги (
git-*): хранить, пока на них ссылается хоть один «человеческий» тег; «осиротевшие» SHA удалять через 30 дней.
Важно: перед включением агрессивной очистки сделайте dry‑run, а лучше — пару ручных проходов с логированием, чтобы не потерять нужные прод‑сборки.
Нейминг и политики: почему они должны проектироваться вместе
Если заранее продумать формат тегов, потом гораздо проще писать правила retention. Например:
- Все теги с суффиксом
-prodсчитаем продовыми. - Все теги с префиксом
feature-считаем краткоживущими. - Все теги формата
YYYY.MM.DD-*можно фильтровать по дате.
Если же разработчики свободно комбинируют произвольные строки в тегах, написать корректные политики без случайных потерь очень сложно.

Организация доступа и изоляция: namespaces как граница ответственности
Даже если у вас один реестр, это не значит, что все должны видеть все образы. Приватные проекты, внешние подрядчики, staging‑окружения — всё это лучше изолировать.
Границы доступа: по org, по команде или по проекту
Варианты разграничения прав для DevOps‑команд:
- По org (internal/external/experiments) — грубая, но простая модель.
- По команде (
/pay,/ml,/core) — популярный вариант: команда отвечает за «своё дерево» namespace. - По проекту — подходит, если команды сильно пересекаются по зонам ответственности.
Важно договориться, кто может пушить в prod-ориентированные теги. Часто имеет смысл запретить прямой пуш *-prod из CI отдельного сервиса, а разрешать только через центральный release‑пайплайн.
Нет ли смысла делать несколько реестров?
Иногда для изоляции выбирают не namespace, а отдельные инсталляции Registry: например, registry-prod.corp.local и registry-dev.corp.local. С точки зрения безопасности это может быть оправдано (особенно в больших организациях), но сопровождаемость и кэш‑хиты часто страдают.
Компромиссный вариант — единый реестр с жёстким RBAC и чётко разделёнными namespace. Тогда инфраструктурные расходы ниже, а границы ответственности всё равно есть.
SSL для Docker Registry: не откладывать «на потом»
Docker‑клиент по умолчанию ожидает, что реестр работает по HTTPS с корректным сертификатом. Можно «временно» включить insecure registry и использовать HTTP, но это быстро превращается в постоянное небезопасное решение.
Почему SSL обязателен в реальных окружениях
При работе с Registry по HTTP вы получаете сразу несколько проблем:
- Пароли и токены идут в открытом виде (даже если это Basic Auth).
- Образы можно подменить при атаке «человек посередине».
- Часть инструментов и оркестраторов в продакшене вообще не любят insecure registry.
Даже если ваш реестр формально «внутренний», это не снимает риск подмены артефактов и утечки учётных данных. Шифрование трафика и проверка подлинности сервера через TLS сегодня — базовый стандарт.
Для публичных сервисов и внешних реестров вы можете использовать коммерческие SSL-сертификаты с понятной цепочкой доверия, чтобы разработчики и CI‑окружения не боролись с ошибками проверки CA.
Домены и сертификаты для Registry
Проектируя адреса реестра, сразу заложите нормальные доменные имена, а не сырые IP:
registry.corp.local— основной реестр.registry-stage.corp.local— если решили разносить окружения по разным инстансам.registry-cache.corp.local— прокси‑кеш для публичных образов (если используете).
С точки зрения SSL можно использовать как отдельные сертификаты на каждый домен, так и SAN‑сертификаты, покрывающие несколько имён. Внутренний реестр нередко защищают сертификатом от внутреннего корпоративного УЦ, чтобы не завязываться на публичные ACME‑процессы.
Корневой CA и Docker‑клиент
Если ваш Registry подписан не публичным CA, а корпоративным или самоподписанным, Docker‑клиенту нужно «объяснить», что этот CA доверенный. Обычно это делается так:
- Сертификат корневого CA разворачивается по серверам и CI‑раннерам (через конфигурацию ОС).
- Для Docker добавляются соответствующие файлы в каталог доверенных CA (зависит от дистрибутива и версии Docker).
Без этого docker login/pull будут падать с ошибками проверки цепочки сертификатов, и разработчики начнут злоупотреблять флагами insecure registry.
Reverse proxy перед Registry
Частая и удобная схема — вынести TLS‑терминацию на reverse proxy (например, Nginx или Caddy), а сам реестр оставлять слушать HTTP на localhost или внутреннем интерфейсе.
Преимущества:
- Можно унифицировать конфигурации SSL (одни и те же шифры, протоколы, OCSP‑stapling и так далее).
- Проще менять сертификаты и перенастраивать TLS без перезапуска Registry.
- Удобно встраивать аутентификацию по токенам, IP‑фильтрацию, rate limiting и другие политики доступа.
В этом случае Docker Registry работает как обычный бэкенд за HTTPS‑фронтендом, а DevOps управляют TLS точно так же, как для любых других веб‑сервисов.

Политики безопасности вокруг Registry
SSL — только один элемент общей политики. Чтобы реестр не стал слабым звеном в цепочке поставки, нужно продумать и другие аспекты.
Аутентификация и авторизация
Реестр должен однозначно знать, кто и что делает:
- Запрет анонимного пуша (pull при необходимости можно оставить публичным для отдельных namespace).
- Интеграция с корпоративной аутентификацией (LDAP/AD/OIDC) — меньше локальных учёток, больше контроля.
- Ролевые модели: кто может создавать/удалять репозитории, кто может менять политики, кто может пушить в «продовые» namespace.
Чем ближе модель к привычной RBAC системы CI/CD и оркестрации, тем проще сопровождать.
Минимизация прав для CI/CD
Типовая ошибка — отдавать CI‑раннерам «всемогущие» токены к Registry. Лучше завести отдельные учётки или токены:
- На каждый проект или группу проектов свой токен.
- Право push только в «свои» namespace.
- Если возможно — раздельные токены для push и pull.
При компрометации runner или окружения злоумышленник не сможет залезть в образы других команд или переписать критичные продовые теги за пределами своего scope.
Если вы строите окружения на собственных серверах или облачном VDS, заранее заложите шаблоны ролей и токенов в базовые образы агентов CI/CD, чтобы конфигурация прав была единообразной.
Логирование и аудит
Реестр — часть цепочки поставки ПО, а значит любые операции с образами должны быть наблюдаемы:
- Кто и когда запушил новый образ или тег.
- Кто и когда удалил репозиторий или старые теги.
- Необычные паттерны запросов на pull (потенциальная утечка или сканирование).
Логи Registry и reverse proxy стоит собирать в общую систему логирования или SIEM, чтобы можно было расследовать инциденты и строить базовые оповещения.
Отдельно полезно интегрировать реестр с резервным копированием CI и инфраструктуры: подробнее о практиках восстановления окружений мы разбирали в статье о резервном копировании CI и sandbox‑окружений.
Практический пример: путь от хаоса к структуре
Рассмотрим типичный сценарий развития Registry в компании.
Стартовая точка:
- Один реестр
registry.local:5000без домена и без SSL. - Один namespace
/projectдля всего. - Теги произвольные:
latest,v1,vasya-test. - Диски начинают заполняться, никто не понимает, что можно удалить.
Желаемое состояние через несколько итераций:
- Реестр доступен по нормальному домену
registry.corp.localс валидным SSL. - Введена иерархия namespace по командам и продуктам.
- Определён формат тегов:
git-SHA, семвер‑теги, окруженческие теги. - Работают автоматические политики retention, сохраняющие только «нужное».
- Доступ к реестру интегрирован с корпоративной аутентификацией; у CI — минимально необходимые права.
Переход выполняется по шагам:
- Поднимается новый Registry (или reverse proxy) с доменом и SSL.
- Переезжают проекты, где изменить нейминг проще всего (новые или малозависимые сервисы).
- По согласованной схеме обновляются пайплайны CI/CD под новый формат namespace и тегов.
- Добавляются политики retention сначала в режиме мониторинга (логировать, что бы могли удалить).
- После проверки политики включаются в боевом режиме.
Если вам интересна изоляция контейнеров в проде, к реестру логично добавить и продуманную изоляцию рантайма: мы подробно разбирали это в материале про gVisor и Firecracker для изоляции контейнеров.
Главное — вложить время в обсуждение и дизайн схемы, а не сразу бежать писать скрипт очистки. В противном случае вы рискуете зацементировать неудобную структуру ещё на пару лет.
Итоги
Организация Docker Registry в компании — это не только «где запустить контейнер и куда примаунтить диск». Важно продумать четыре взаимосвязанных уровня:
- Нейминг и namespace — чтобы имена образов были однозначными и «читабельными» как для людей, так и для CI/CD.
- Tag policies — чтобы каждый релиз был воспроизводим, а
latestне управлял продом. - Retention policies — чтобы реестр не разрастался бесконтрольно, но при этом сохранял важные релизы.
- Безопасность и SSL — чтобы доступ к образам был защищён, контролируем и аудируем.
Подходите к Registry как к критичному инфраструктурному сервису: зафиксируйте правила нейминга и политики в документации, автоматизируйте их в CI/CD и в самом реестре. Это сэкономит много часов расследований и «ручных» чисток спустя год активной работы команды.


