Реестры в продакшене: Harbor и облачные registry

Рейтинг: 72.2% · 10 голосов
Практический курс по Docker: образы, контейнеры, тома, сети, Compose и продакшен. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
Marina_DevOps
Сообщения: 54
Зарегистрирован: 11 май 2026, 05:31

Реестры в продакшене: Harbor и облачные registry

Сообщение Marina_DevOps »

Оглавление курса (46)
  1. Что такое Docker и какие задачи он решает
  2. Установка Docker и запуск первого контейнера
  3. Образы: слои, теги и реестр Docker Hub
  4. Пишем свой Dockerfile
  5. Тома и хранение данных: volumes и bind mounts
  6. Сети в Docker: связываем контейнеры между собой
  7. Переменные окружения и конфигурация контейнеров
  8. Docker Compose: поднимаем многоконтейнерное приложение
  9. Оптимизация образов: multi-stage сборка, размер и кэш слоёв
  10. Логи, отладка и мониторинг контейнеров
  11. Базовая безопасность контейнеров
  12. Подготовка к продакшену: что важно учесть
  13. Dockerfile глубже: ENTRYPOINT и CMD, HEALTHCHECK, .dockerignore, запуск не от root
  14. Реестры образов: приватные registry, push и pull, теги и digest, imagePullSecrets
  15. BuildKit и buildx: multi-arch сборки, секреты сборки, экспорт кэша
  16. Docker в CI/CD: автосборка, сканирование образов (Trivy, Docker Scout), публикация
  17. Итоговый проект и куда расти: от Dockerfile до прода, обзор оркестрации (Kubernetes, Podman, OCI)
  18. Архитектура Docker: dockerd, containerd, runc и OCI
  19. Как работает изоляция: namespaces и cgroups
  20. Образы изнутри: слои, OverlayFS и storage driver
  21. Жизненный цикл контейнера и политики перезапуска
  22. Отладка контейнеров: exec, attach, nsenter, debug
  23. Сети Docker глубже: bridge, overlay, macvlan и iptables
  24. Docker Compose глубже: profiles, healthcheck-зависимости, override
  25. Данные и тома глубже: драйверы, бэкап, права
  26. Секреты и конфигурация: как не светить пароли
  27. Ограничение ресурсов: CPU, память, OOM и cgroups
  28. Здоровье и автозапуск: HEALTHCHECK, init и сигналы
  29. Логирование контейнеров: драйверы, ротация, сбор
  30. Мониторинг контейнеров: stats, cAdvisor, Prometheus
  31. Безопасность глубже: rootless, user namespaces, seccomp, capabilities
  32. Supply chain: сканирование, SBOM и подпись образов
  33. Глубокая оптимизация образов: distroless, scratch, кэш
  34. Multi-arch и сборка под ARM: buildx и эмуляция
  35. Реестры в продакшене: Harbor и облачные registry (вы здесь)
  36. Docker без Docker: Podman, containerd, nerdctl, Buildah
  37. От Compose к оркестрации: когда контейнеров становится много
  38. Docker Swarm: встроенная оркестрация
  39. Сборка образов в CI без демона: kaniko, BuildKit, Buildah
  40. Траблшутинг Docker: типичные ошибки и как чинить
  41. Производительность и эксплуатация Docker-хоста
  42. Docker Desktop, WSL2 и альтернативы на Windows и Mac
  43. Контейнеризация приложений: бэкенд, фронтенд, БД
  44. Docker и Kubernetes: containerd, миграция, kompose
  45. Лучшие практики и антипаттерны Docker
  46. Сквозной проект: production-ready стек и путь дальше
Зачем команде свой реестр и почему docker push в Hub - это не прод

На ноутбуке ты собираешь образ и пушишь его в Docker Hub. Один человек, один аккаунт, паблик-репозиторий - всем удобно. А теперь представь команду из пятнадцати человек, CI, который собирает по сотне образов в день, прод, который дёргает pull тысячу раз в сутки при автоскейле, и требование безопасников: ни один уязвимый образ не должен доехать до кластера. Hub в бесплатном режиме тут разваливается: rate limit на анонимные и бесплатные pull, публичность по умолчанию, ноль RBAC, ноль сканирования, ноль контроля над тем, кто и что выкладывает. Плюс в РФ к этому добавляется простая боль - доступность registry-1.docker.io то есть, то нет, и твой деплой встаёт колом на ровном месте.

Приватный реестр docker (private registry) - это место, где живут образы твоей команды. По сути это HTTP-сервис, реализующий Docker Registry HTTP API V2 (он же OCI Distribution Spec). Любой клиент - docker, containerd, podman, buildkit - общается с ним по одному и тому же протоколу: проверяет манифест, тянет слои по их sha256-дайджесту, заливает блобы. Поэтому registry, Harbor, Yandex Container Registry и GitHub Container Registry снаружи выглядят одинаково. Разница - в том, что навешано вокруг: аутентификация, права, сканирование, репликация, чистка, квоты. Именно это отличает container registry для прода от игрушки. В этом уроке разберём механику и научимся выбирать.

Изображение

registry:2 - минимальный docker registry под капотом

Начнём с самого простого, чтобы понять, что внутри. Опенсорсный registry (проект CNCF Distribution) - это и есть тот самый референс-сервер. Поднимается одной командой:

Код: Выделить всё

docker run -d --name registry --restart=always \
  -p 5000:5000 \
  -v /opt/registry/data:/var/lib/registry \
  registry:2
Внутри контейнера всё, что он умеет, лежит в /var/lib/registry. Загляни туда после первого push - увидишь структуру docker/registry/v2 с двумя ветками: blobs (сами слои и конфиги, адресуемые по содержимому, то есть имя папки - это sha256 контента) и repositories (метаданные: какие теги на какой манифест указывают). Ключевая идея - content-addressable storage: один и тот же слой, который встречается в десяти образах, физически хранится один раз. Это и причина того, почему чистка реестра нетривиальна, к ней вернёмся.

Тегируем образ адресом реестра и пушим:

Код: Выделить всё

docker tag myapp:1.0 registry.local:5000/team/myapp:1.0
docker push registry.local:5000/team/myapp:1.0
Адрес реестра - это префикс имени образа. Нет префикса (просто nginx:latest) - значит docker.io. Есть - значит туда и идём. Запомни это, половина граблей с реестрами растёт из непонимания, что хост зашит в само имя образа.

Здесь же первая стена - HTTPS. Демон Docker по умолчанию отказывается работать с реестром по голому HTTP. Попробуешь push на http-only порт - получишь:

Код: Выделить всё

http: server gave HTTP response to HTTPS client
Два пути. Грязный (для лабы) - объявить реестр небезопасным в /etc/docker/daemon.json:

Код: Выделить всё

{
  "insecure-registries": ["registry.local:5000"]
}
после чего systemctl restart docker. Правильный (для прода) - дать реестру нормальный TLS-сертификат. Если он от публичного CA (Let's Encrypt) - всё заработает само. Если self-signed - надо положить твой CA-сертификат туда, где его ищет клиент: /etc/docker/certs.d/registry.local:5000/ca.crt для Docker и /etc/containerd/certs.d/... для containerd. Имя папки - ровно хост:порт реестра, это частый промах. Без этого получишь x509: certificate signed by unknown authority, и никакой docker login не поможет, потому что TLS отваливается раньше авторизации.

Минусы registry:2 как продового решения очевидны ровно в момент, когда команда становится больше одного человека: аутентификация только через внешний htpasswd или reverse-proxy, нет понятия пользователей и ролей, нет UI, нет сканирования, нет нормальной чистки из коробки. Он отличен как встроенный кирпичик (например, как pull-through cache - об этом ниже) или как registry внутри CI. Но как командный реестр он голый.

Harbor registry: что добавляет enterprise-обвязка

Harbor (тоже проект CNCF, актуальная ветка в 2026 - 2.1x, на момент урока релизы линии 2.14/2.15) - это registry:2 внутри плюс целый слой управления сверху. Когда говорят harbor registry в контексте прода, имеют в виду именно эту обвязку. Разберём по кусочкам, потому что каждый пункт закрывает конкретную боль.

Проекты и RBAC. В Harbor образы лежат не плоско, а в проектах. Проект - это и неймспейс (harbor.company.ru/payments/api), и граница доступа, и единица настроек (квоты, политики). Внутри проекта пользователю выдаётся роль: Limited Guest (только pull), Guest (pull), Developer (push+pull), Maintainer (плюс сканирование и управление тегами), ProjectAdmin (всё, включая членов и политики). Сам проект - публичный или приватный. Это и есть RBAC, которого нет в registry:2: ты раздаёшь права не на весь реестр, а точечно. Пользователи живут либо локально, либо приходят из LDAP/AD или OIDC (Keycloak, корпоративный SSO) - в проде почти всегда второе, чтобы не плодить учётки.

Сканирование уязвимостей (Trivy). Harbor из коробки идёт со сканером Trivy как дефолтным (исторически был ещё Clair, сейчас стандарт - Trivy). Сканер разбирает образ послойно, достаёт список установленных пакетов (apt, apk, npm, pip, gem и т.д.) и сверяет версии с базами CVE. Главная фишка - политика на уровне проекта: можно включить scan on push (каждый запушенный образ сразу сканируется) и, что важнее, prevent vulnerable images from running - запрет pull образов с уязвимостями выше заданного порога (например, Critical и High). То есть это не отчёт ради отчёта, а реальный шлюз: уязвимый образ физически не вытянется в кластер. Базы CVE стареют, поэтому в Harbor есть и периодическое пересканирование - вчера чистый образ сегодня может стать дырявым, если выкатили новую CVE.

Подпись образов. Образ - это просто данные на сервере, их теоретически можно подменить. Подпись доказывает, что образ собран доверенной стороной и не изменён после. Старый механизм Notary v1 (Docker Content Trust) в современной экосистеме считается легаси; индустрия ушла на Sigstore cosign, который кладёт подпись рядом с образом как отдельный артефакт в том же реестре. На стороне кластера политику подписи проверяют admission-контроллеры (Kyverno, OPA Gatekeeper, политики Harbor/Connaisseur). Практически: в CI после push делаешь cosign sign, в кластере не пускаешь неподписанное.

Репликация. Политика репликации тянет или толкает образы между реестрами по фильтрам (репозиторий, тег, метка). Сценарии из жизни: реплика Harbor в другом дата-центре или регионе для отказоустойчивости и близости к кластеру (pull по локальной сети, а не через полмира); зеркало образов из внешнего реестра (тот же Docker Hub) внутрь периметра, чтобы не зависеть от его доступности. Репликация бывает push (этот Harbor отправляет) и pull (этот забирает у другого), по расписанию или по событию.

Retention и квоты. CI генерирует теги пачками - на каждый коммит образ, и место кончается за недели. Tag retention policy в Harbor задаётся декларативно на проект: например, держать последние 10 тегов на репозиторий плюс всё, что матчится по маске prod-* и release-*, остальное - под снос. Квоты ограничивают объём проекта в гигабайтах, чтобы одна команда не съела весь диск. Tag immutability отдельно запрещает перезапись тега (чтобы myapp:1.0 нельзя было втихую подменить - критично для воспроизводимости).

Proxy cache (pull-through). Harbor умеет быть кеширующим прокси к внешнему реестру: создаёшь проект типа proxy cache, указываешь upstream (Docker Hub, GHCR, Quay), и при первом pull через него Harbor скачивает образ наружу, кладёт к себе и отдаёт. Дальше всё тянется уже локально. Это прямое лекарство от двух болей разом - rate limit Docker Hub и его недоступности в РФ.

Облачные registry: Yandex, VK, GitHub/GitLab, Nexus

Поднимать и обслуживать Harbor (а это база данных, Redis, сам registry, сканер, job-сервис, обновления, бэкапы, TLS) - работа. Если не хочешь её делать, берёшь managed registry в облаке. Снаружи протокол тот же V2/OCI, отличается биллинг, интеграция с IAM и регион.

Yandex Container Registry. Российский управляемый реестр, частый дефолт для команд на Yandex Cloud. Логин - не пароль, а IAM-токен или сервисный аккаунт. На практике:

Код: Выделить всё

yc container registry configure-docker
docker tag myapp:1.0 cr.yandex/<registry-id>/myapp:1.0
docker push cr.yandex/<registry-id>/myapp:1.0
Команда configure-docker прописывает в ~/.docker/config.json кредент-хелпер, который сам подкладывает свежий токен при каждом обращении - руками docker login делать не надо. Есть сканер уязвимостей, lifecycle policy (аналог retention - чистка старых образов по правилам), приватность по умолчанию и хостинг внутри РФ, что снимает вопросы доступности и комплаенса. Похожий по идее сервис у VK Cloud (VK Cloud Container Registry) - тоже managed, тоже IAM-аутентификация, тоже внутри РФ. Для прода в России именно близость и стабильность реестра часто перевешивают фичи.

GitHub Container Registry (ghcr.io) и GitLab Container Registry. Их сила - в том, что реестр сросся с CI/CD и репозиторием кода. У GitLab каждый проект автоматически получает свой registry, образы пушатся прямо из пайплайна предопределёнными переменными ($CI_REGISTRY, $CI_REGISTRY_IMAGE), а CI_JOB_TOKEN авторизует push без хранения отдельных секретов. У GitHub - ghcr.io с правами через GITHUB_TOKEN в Actions. Минус для РФ - доступность обоих к GitHub/GitLab.com нестабильна, для прода внутри страны это риск.

Nexus (Sonatype) и Artifactory. Это универсальные репозитории артефактов: Docker - лишь один из форматов рядом с Maven, npm, PyPI, apt. Берут, когда в компании уже есть Nexus/Artifactory под джавовые или питоновские зависимости, и логично хранить docker-образы там же, в одном месте с единым доступом. Они тоже умеют proxy-репозитории (pull-through кеш) и group-репозитории, объединяющие несколько источников за одним адресом.

Грубое правило выбора. Внутренний прод в РФ, нужен полный контроль, RBAC, сканирование, подпись, репликация - Harbor self-hosted или Yandex/VK managed. Уже живёшь в GitLab/GitHub и команда небольшая - их встроенный registry. Уже есть Nexus/Artifactory под другие артефакты - доложи туда же docker.

Аутентификация, imagePullSecrets и чистка места

Когда реестр приватный, кластеру надо как-то логиниться, чтобы тянуть образы. На уровне Docker всё просто:

Код: Выделить всё

docker login harbor.company.ru
# далее логин/пароль или robot-токен, кредент пишется в ~/.docker/config.json
В Harbor для CI и кластеров не используют живые учётки людей - заводят robot account: технический пользователь с длинным токеном, ограниченными правами (только pull нужного проекта) и сроком жизни. Скомпрометировали - отозвали один токен, не трогая людей.

В Kubernetes этот config.json превращается в Secret типа dockerconfigjson, на который ссылается imagePullSecrets:

Код: Выделить всё

kubectl create secret docker-registry harbor-cred \
  --docker-server=harbor.company.ru \
  --docker-username='robot$ci+pull' \
  --docker-password='<token>' \
  -n payments
Дальше секрет указывают либо в поле imagePullSecrets пода/деплоймента, либо привязывают к ServiceAccount, чтобы все поды в неймспейсе тянули приватные образы автоматически. Типовая ошибка - ErrImagePull/ImagePullBackOff в kubectl describe pod с текстом про unauthorized: секрет либо не в том неймспейсе (Secret привязан к неймспейсу!), либо не подключён к поду, либо server в нём написан не как в имени образа. У облаков с IAM (Yandex/VK) часто есть свой механизм - права даются сервис-аккаунту узлов, и imagePullSecrets не нужен вовсе.

Теперь про место - то, обо что спотыкаются все. Когда ты delete тег или retention снёс его, образ не освобождает диск. Удаляется лишь ссылка тег -> манифест. Сами blob-ы (слои) остаются лежать в storage как untagged, потому что content-addressable хранилище не знает, не сошлётся ли на них кто-то ещё. Реальное освобождение делает garbage collection - отдельный проход, который находит блобы, на которые больше не ссылается ни один манифест, и физически их стирает. В registry:2:

Код: Выделить всё

docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
В Harbor GC запускается из UI или по расписанию (Administration -> Clean Up). Важный нюанс: классический GC требует, чтобы реестр был в read-only на время прохода (иначе можно удалить блоб, который прямо сейчас загружается параллельным push) - в registry:2 это флаг REGISTRY_STORAGE_MAINTENANCE_READONLY. Поэтому связка такая: retention режет теги -> GC по расписанию забирает место. Без GC retention лишь прячет образы из списка, а диск продолжает течь, и в один день у тебя no space left on device на хосте реестра.

Типичные грабли и антипаттерны
  • insecure-registries в проде. Удобно в лабе, дыра в проде: трафик и кред019енты можно перехватить. Всегда нормальный TLS, self-signed CA раздавай в /etc/docker/certs.d/ и /etc/containerd/certs.d/.
  • Папка сертификата названа неправильно. Для хоста с портом нужна папка ровно registry.local:5000, а не registry.local. Не совпало - x509 unknown authority.
  • Думать, что delete освобождает место. Не освобождает. Нет регулярного GC - реестр распухает молча. Настрой retention И garbage collection вместе.
  • latest в проде и перезапись тегов. Тянешь по latest - не знаешь, что именно приехало. Деплой по неизменяемому тегу или по дайджесту (@sha256:...), включи tag immutability.
  • Сканирование как украшение. Если Trivy просто рисует отчёт, а pull уязвимого образа не блокируется - это театр. Включай enforcement (prevent vulnerable from running).
  • Живые учётки людей в CI и кластере. Используй robot-аккаунты и сервисные токены с минимальными правами и сроком жизни.
  • Один Harbor без бэкапа и без реплики. Реестр лёг - встал весь деплой и автоскейл. Для прода - репликация и бэкап БД с storage.
Мини-лаба: свой реестр за полчаса
  • Подними registry:2 локально с volume на /var/lib/registry. Запушь туда любой образ под именем localhost:5000/test/app:1.0. Загляни в каталог данных и найди папки blobs и repositories - убедись, что слои адресуются по sha256.
  • Дёрни каталог реестра через API: curl http://localhost:5000/v2/_catalog и curl http://localhost:5000/v2/test/app/tags/list - увидишь те же данные, что отдаёт UI любого большого реестра, протокол один.
  • Сломай TLS специально: попробуй push на реестр без insecure-registries и без сертификата, прочитай ошибку, потом почини через daemon.json. Прочувствуй, на каком шаге всё падает.
  • Если есть доступ к облаку - заведи Yandex или VK Container Registry, выполни configure-docker, запушь образ и посмотри, как кредент-хелпер логинит тебя без явного docker login.
  • Подними Harbor по официальному offline-инсталлеру, создай приватный проект, robot-аккаунт с правом pull, включи scan on push, запушь заведомо старый образ (например, старый debian) и посмотри отчёт Trivy. Настрой tag retention на 3 последних тега.
Контрольные вопросы
  • Почему удаление тега в реестре не освобождает место на диске и что именно его освобождает?
  • Чем proxy cache (pull-through) проект Harbor помогает против rate limit и недоступности Docker Hub в РФ?
  • Где физически должен лежать CA-сертификат self-signed реестра, чтобы docker и containerd ему доверяли, и почему важно имя папки?
  • Что такое imagePullSecrets, почему ошибка чаще всего в неймспейсе секрета и чем robot-аккаунт лучше учётки человека?
Итог

Любой реестр снаружи - это один и тот же OCI Distribution API: манифесты и слои по дайджесту. registry:2 показывает голую механику и годится как кирпичик или кеш. Harbor добавляет то, без чего нет командного прода: проекты и RBAC, сканирование Trivy с блокировкой, подпись, репликацию, retention и квоты, proxy cache против болей Docker Hub. Облачные registry (Yandex, VK, GHCR, GitLab, Nexus) снимают эксплуатацию, отдавая контроль и привязываясь к своему IAM. А две вещи держи в голове всегда: TLS и доверие к сертификату решают, заработает ли pull вообще, а связка retention + garbage collection решает, не утонет ли реестр в собственных слоях.
👍4 ❤️2 🔥1 😄 🤔1
Аватара пользователя
mrpurli
Сообщения: 1
Зарегистрирован: 02 июн 2026, 20:15

Re: Реестры в продакшене: Harbor и облачные registry

Сообщение mrpurli »

Месяцами не мог понять, почему реестр пухнет, хотя я регулярно сношу старые теги. Оказалось retention без GC это просто косметика. Запустил garbage-collect в read-only и освободил под 200 гигов разом, спасибо за разбор про untagged блобы.
👍1 ❤️1 🔥 😄 🤔2
Аватара пользователя
pzflash2
Сообщения: 1
Зарегистрирован: 14 май 2026, 14:10

Re: Реестры в продакшене: Harbor и облачные registry

Сообщение pzflash2 »

Вопрос про self-signed: у меня docker login проходит, а pull валится на x509 unknown authority. Папку сделал /etc/docker/certs.d/harbor.company.ru/ca.crt без порта, а реестр на 8443. В этом дело? Похоже надо harbor.company.ru:8443?
👍 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Multi-arch и сборка под ARM: buildx и эмуляция
Следующая глава →
Docker без Docker: Podman, containerd, nerdctl, Buildah

Все главы курса «Docker: контейнеризация от основ до продакшена»

Поделиться темой: ✈ Telegram VK
Похожие запросы: как поднять приватный docker registry push pull и digestharbor реестр образов что это и чем отличается от registry

Вернуться в «Docker с нуля»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость