Главная/Материалы/Материал

local-registry

Локальный registry для проверки процесса доставки. Показывает, что registry — это HTTP-хранилище с адресуемым по содержимому содержимым, а не чёрный ящик внутри Docker.

Используется в разделе 14.

Что демонстрирует

  • registry как обычный HTTP API: всё, что делает docker push, повторяется curl;
  • три разных digest'а одного образа и то, какой годится для закрепления;
  • дедупликация слоёв работает в пределах репозитория — в другом репозитории они передаются заново;
  • удаление образа возможно только по digest, а не по тегу;
  • место освобождается не при удалении, а при сборке мусора — это отдельный шаг.

Запуск

bash
docker compose up -d
curl -s http://127.0.0.1:5000/v2/     # {} означает, что API работает

С веб-интерфейсом:

bash
docker compose --profile ui up -d
# http://127.0.0.1:5001

Скрипты

text
scripts/lib.sh          общее: адрес registry, коды возврата, обёртка над API
scripts/push-demo.sh    собрать два образа и выгрузить
scripts/inspect.sh      осмотр через HTTP API, БЕЗ docker
scripts/dedup-demo.sh   дедупликация в пределах репозитория
scripts/cleanup.sh      удаление по digest и сборка мусора

Каждый различает три состояния:

КодЗначение
0Выполнено
1Registry недоступен
3Не выполнялось: нет docker
bash
./scripts/push-demo.sh; echo "код: $?"
text
[14:29:31] НЕ ПРОВЕРЕНО: docker недоступен; сборка и выгрузка не выполнялись
код: 3

Что стоит посмотреть

Registry — это HTTP

scripts/inspect.sh не использует docker вообще:

bash
./scripts/push-demo.sh
./scripts/inspect.sh
text
── репозитории ──
{"repositories": ["demo"]}

── теги demo ──
{"name": "demo", "tags": ["1.0.0", "1.0.1"]}

── digest каждого тега ──
  1.0.0      sha256:9f8e7d6c5b4a3210…
  1.0.1      sha256:1a2b3c4d5e6f7a8b…

── слои первого тега ──
  конфигурация: sha256:aaaa0000bbbb1111c… 1842 байт
  слой 1: sha256:cccc2222dddd3333e… 29154416 байт
  слой 2: sha256:eeee4444ffff5555a… 3271 байт

То же руками:

bash
curl -s http://127.0.0.1:5000/v2/_catalog
curl -s http://127.0.0.1:5000/v2/demo/tags/list
curl -sI -H 'Accept: application/vnd.oci.image.manifest.v1+json' \
     http://127.0.0.1:5000/v2/demo/manifests/1.0.0 | grep -i digest

Дедупликация — только в пределах репозитория

bash
./scripts/dedup-demo.sh
text
[14:31:02] тот же репозиторий, другой тег — слои НЕ передаются
      3 Layer already exists

[14:31:04] другой репозиторий — слои передаются ЗАНОВО
      3 Pushed

Это удивляет чаще всего: тот же образ, тот же registry, те же слои — и полная передача. Дедупликация — свойство хранилища ссылок репозитория, а не registry целиком.

Практическое следствие: перенос образов между репозиториями (например, из staging в production) стоит полного трафика. Дешевле пометить тегом внутри одного репозитория.

Удаление по digest, а не по тегу

bash
./scripts/cleanup.sh 1.0.0
text
[14:33:10] удаляю манифест sha256:9f8e7d6c5b4a3210…
[14:33:10] манифест удалён
[14:33:11] сборка мусора (место освобождается только здесь)

Удалить по тегу нельзя: тег — ссылка на манифест, а удаляется манифест. Отсюда два следствия:

  1. Удаление одного тега делает недоступными все теги, указывающие на тот же манифест.
  2. Место не освобождается до сборки мусора — а она требует отдельного запуска и, в некоторых версиях, остановки записи.

Три digest'а одного образа

text
index (список манифестов)     ← для многоплатформенных образов
  └─ manifest linux/amd64     ← ЭТОТ показывает RepoDigests
       ├─ config              ← ЭТОТ показывает docker images
       └─ слои

Для закрепления версии годится тот, что показывает RepoDigests:

bash
docker image inspect 127.0.0.1:5000/demo:1.0.0 --format '{{index .RepoDigests 0}}'

Чего этого недостаточно для эксплуатации

Пример намеренно упрощён. Ниже — то, чего в нём нет и что обязательно в работе:

Чего нетПочему нужно
TLSБез него содержимое передаётся открыто
АутентификацияВыгрузить может кто угодно
Сборка мусора по расписаниюМесто не освобождается само
Резервное копирование томаRegistry — это данные
Ограничение на удалениеDELETE включён для демонстрации
Проверка подписейНичто не мешает выгрузить что угодно

Первые две строки — причина, по которой ports привязаны к 127.0.0.1: этот registry не должен быть доступен из сети.

Отдельно про TLS. Он защищает содержимое при передаче, но не защищает от подмены манифеста по тегу: тег изменяем, и подмена законна с точки зрения протокола. От неё защищает закрепление по digest — и оно работает даже без TLS.

Чего пример не делает

Ничего из перечисленного не запускалось. Docker на машине, где готовился курс, отсутствует. Проверено то, что проверяется без него: синтаксис всех пяти скриптов, разбор compose.yaml, валидность app.py, и то, что скрипты корректно отказывают:

text
inspect  (нет registry): 1
push     (нет docker):   3
dedup    (нет docker):   3
cleanup  (нет registry): 1

Вывод команд в этом файле — реконструкция по документации Distribution, а не запись сеанса. Проверьте у себя.

Размеры слоёв в примере вывода вымышлены. Настоящие зависят от базового образа.


Навигация

Все примеры
Раздел 14. Registry
Урок 14.3. Локальный registry
Урок 14.4. Стратегия тегов

Markdown на GitHub ↗