Реестры образов: Docker Hub и приватные
Где живут собранные образы и как их грамотно публиковать, версионировать и хранить.
Реестр (registry) — сервер-хранилище Docker-образов: вы загружаете туда образ командой
pushи скачиваете на любой машине командойpull.
Собрать образ через docker build — это полдела. Образ лежит на вашем ноутбуке, а нужен он на сервере, у коллеги и в CI. Копировать его флешкой никто не будет. Реестр решает эту задачу: вы публикуете образ один раз, а дальше любая машина с доступом к реестру скачивает ровно тот же бинарный артефакт. Самый известный публичный реестр — Docker Hub, но в реальных командах чаще встречаются приватные: GitHub Container Registry (ghcr.io), GitLab Registry, Amazon ECR, Yandex Container Registry или собственный сервер.
Зачем это на практике
Реестр — это «общая правда» о том, какой образ считается готовым. Разработчик собрал и запушил myapp:1.4.2, CI прогнал тесты, сервер скачал тот же тег — и все работают с идентичным набором байтов. Это устраняет классическое «у меня локально работало»: на проде крутится не пересобранный заново образ, а тот же самый, что прошёл проверки.
Адрес образа: как он устроен
Полное имя образа складывается из четырёх частей: реестр/пространство-имён/репозиторий:тег. Если реестр не указан, Docker подразумевает Docker Hub, а если не указан тег — подставляет latest.
docker.io/library/nginx:1.27 # официальный nginx с Docker Hub
ghcr.io/acme/api:1.4.2 # приватный образ в GitHub Container Registry
registry.gitlab.com/team/web:dev # образ в GitLab Registry
Понимать структуру имени важно, потому что именно по нему Docker решает, куда идти за образом и куда его публиковать.
Логин, push и pull
Чтобы публиковать в приватный реестр, нужно сначала аутентифицироваться. Команда docker login сохраняет токен, и дальше push/pull работают прозрачно.
# Вход в Docker Hub (логин/пароль или access token)
docker login -u myuser
# Вход в приватный реестр — указываем его адрес
docker login ghcr.io -u myuser
# Собираем образ сразу с «правильным» именем под реестр
docker build -t ghcr.io/acme/api:1.4.2 .
# Публикуем
docker push ghcr.io/acme/api:1.4.2
# На другой машине — скачиваем
docker pull ghcr.io/acme/api:1.4.2
Важная деталь: имя образа уже содержит адрес реестра. Docker не знает «куда» пушить из отдельной настройки — он смотрит на префикс тега. Хотите в ghcr.io — собирайте образ с тегом ghcr.io/.... Если у вас уже есть образ myapp:1.4.2 без префикса, навесьте второй тег: docker tag myapp:1.4.2 ghcr.io/acme/api:1.4.2, и пушьте новый.
Теги и версионирование
Тег — это человекочитаемая метка поверх образа. Один и тот же образ может иметь несколько тегов. Хорошая стратегия — публиковать иммутабельные теги с конкретной версией и параллельно двигать «плавающие» теги-указатели.
| Тег | Смысл | Меняется? |
1.4.2 | конкретный релиз (semver) | нет, навсегда тот же образ |
1.4 | последний патч минорной версии | да, двигается на 1.4.3, 1.4.4… |
sha-a1b2c3d | образ из конкретного коммита | нет |
latest | «последний» по соглашению | да, перетирается каждым push |
Иммутабельный тег 1.4.2 даёт воспроизводимость: задеплоили в прод именно его — и через месяц этот же тег указывает на тот же образ. По нему можно откатиться, его можно просканировать, на него можно сослаться в инциденте.
Антипаттерн latest
Соблазн деплоить myapp:latest велик, но это ловушка. latest — не «свежайшая версия», а просто строка-тег, которую перетирает каждый push. Из этого следуют беды:
- Непонятно, что именно крутится на проде — какой коммит, какая версия.
docker pull myapp:latestна двух серверах в разные минуты может скачать разные образы.- Откат невозможен: «верни latest назад» не имеет смысла.
- Кэш сбивает с толку: локально
latestстарый, в реестре уже новый.
Правило: в прод деплойте конкретную версию или sha-тег. latest допустим для локальной игры и быстрых демо, но не как источник истины для деплоя.
Приватный registry своими руками
Иногда нужен собственный реестр — внутри закрытого контура или для кэша. Docker предоставляет официальный образ registry, который поднимается одной командой.
# Поднять локальный реестр на порту 5000
docker run -d -p 5000:5000 --restart=always \
-v registry-data:/var/lib/registry \
--name registry registry:2
# Перетегировать и запушить в него
docker tag myapp:1.4.2 localhost:5000/myapp:1.4.2
docker push localhost:5000/myapp:1.4.2
Том registry-data хранит слои на диске, иначе данные исчезнут с контейнером. В реальном проде такой реестр прикрывают TLS и аутентификацией, но для CI-кэша или закрытой сети базовая схема рабочая. Альтернатива «всё своё» — управляемые реестры (ECR, GAR, Yandex CR): за хранение и доступность отвечает провайдер.
Retention: образы копятся бесконечно
Каждый push добавляет слои, и хранилище реестра пухнет: за полгода активной разработки легко набегают сотни гигабайт старых тегов. Retention-политика — это правила автоудаления того, что больше не нужно: «храним последние 10 тегов на репозиторий», «удаляем теги старше 90 дней», «не трогаем теги-релизы v*». В управляемых реестрах это настраивается в их UI/API; в самохостинге запускают registry garbage-collect после удаления тегов, чтобы реально освободить слои.
Как это работает под капотом
Образ — не единый файл, а набор слоёв, каждый адресуется своим SHA256-хешем (это и есть content-addressable storage). При push Docker сначала спрашивает реестр, какие слои уже есть, и заливает только недостающие. Поэтому повторный push похожего образа быстрый: общие базовые слои не передаются. Тег же — это просто запись в манифесте, которая сопоставляет человекочитаемое имя (1.4.2) с хешем-дайджестом (sha256:…). Отсюда мощный приём: можно тянуть образ по дайджесту — docker pull api@sha256:abc123… — и получить гарантированно тот же байт-в-байт образ, даже если кто-то перетёр тег. В критичных деплоях так и делают.
Частые ошибки
- Деплой по
latest. Теряете воспроизводимость и возможность отката. Версионируйте явно. - Забыли префикс реестра при push.
docker push myapp:1.4.2уйдёт на Docker Hub, а не в ваш приватный реестр. Тегируйте с адресом. - Приватный реестр без тома. Перезапустили контейнер
registry— все образы исчезли. Монтируйте volume. - Нет retention. Диск реестра заполняется, push начинает падать. Настройте автоочистку заранее.
- Один тег на всё. Перезаписываете
1.0новыми сборками — невозможно понять, что задеплоено. Иммутабельный тег на релиз.
Итоги
- Реестр — общее хранилище образов;
pushпубликует,pullскачивает,loginаутентифицирует. - Адрес реестра входит в имя образа; нет префикса — значит Docker Hub.
- Версионируйте иммутабельными тегами (
1.4.2,sha-…);latest— антипаттерн для прода. - Тег по дайджесту даёт байт-в-байт воспроизводимость.
- Приватный реестр поднимается образом
registry:2с томом; не забывайте про retention.