local-registry
Локальный registry для проверки процесса доставки. Показывает, что registry — это HTTP-хранилище с адресуемым по содержимому содержимым, а не чёрный ящик внутри Docker.
Используется в разделе 14.
Что демонстрирует
- registry как обычный HTTP API: всё, что делает
docker push, повторяетсяcurl; - три разных digest'а одного образа и то, какой годится для закрепления;
- дедупликация слоёв работает в пределах репозитория — в другом репозитории они передаются заново;
- удаление образа возможно только по digest, а не по тегу;
- место освобождается не при удалении, а при сборке мусора — это отдельный шаг.
Запуск
docker compose up -d
curl -s http://127.0.0.1:5000/v2/ # {} означает, что API работает
С веб-интерфейсом:
docker compose --profile ui up -d
# http://127.0.0.1:5001
Скрипты
scripts/lib.sh общее: адрес registry, коды возврата, обёртка над API
scripts/push-demo.sh собрать два образа и выгрузить
scripts/inspect.sh осмотр через HTTP API, БЕЗ docker
scripts/dedup-demo.sh дедупликация в пределах репозитория
scripts/cleanup.sh удаление по digest и сборка мусора
Каждый различает три состояния:
| Код | Значение |
|---|---|
| 0 | Выполнено |
| 1 | Registry недоступен |
| 3 | Не выполнялось: нет docker |
./scripts/push-demo.sh; echo "код: $?"
[14:29:31] НЕ ПРОВЕРЕНО: docker недоступен; сборка и выгрузка не выполнялись
код: 3
Что стоит посмотреть
Registry — это HTTP
scripts/inspect.sh не использует docker вообще:
./scripts/push-demo.sh
./scripts/inspect.sh
── репозитории ──
{"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 байт
То же руками:
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
Дедупликация — только в пределах репозитория
./scripts/dedup-demo.sh
[14:31:02] тот же репозиторий, другой тег — слои НЕ передаются
3 Layer already exists
[14:31:04] другой репозиторий — слои передаются ЗАНОВО
3 Pushed
Это удивляет чаще всего: тот же образ, тот же registry, те же слои — и полная передача. Дедупликация — свойство хранилища ссылок репозитория, а не registry целиком.
Практическое следствие: перенос образов между репозиториями (например, из staging в production) стоит полного трафика. Дешевле пометить тегом внутри одного репозитория.
Удаление по digest, а не по тегу
./scripts/cleanup.sh 1.0.0
[14:33:10] удаляю манифест sha256:9f8e7d6c5b4a3210…
[14:33:10] манифест удалён
[14:33:11] сборка мусора (место освобождается только здесь)
Удалить по тегу нельзя: тег — ссылка на манифест, а удаляется манифест. Отсюда два следствия:
- Удаление одного тега делает недоступными все теги, указывающие на тот же манифест.
- Место не освобождается до сборки мусора — а она требует отдельного запуска и, в некоторых версиях, остановки записи.
Три digest'а одного образа
index (список манифестов) ← для многоплатформенных образов
└─ manifest linux/amd64 ← ЭТОТ показывает RepoDigests
├─ config ← ЭТОТ показывает docker images
└─ слои
Для закрепления версии годится тот, что показывает RepoDigests:
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, и то, что скрипты корректно отказывают:
inspect (нет registry): 1
push (нет docker): 3
dedup (нет docker): 3
cleanup (нет registry): 1
Вывод команд в этом файле — реконструкция по документации Distribution, а не запись сеанса. Проверьте у себя.
Размеры слоёв в примере вывода вымышлены. Настоящие зависят от базового образа.
Навигация
Все примеры
Раздел 14. Registry
Урок 14.3. Локальный registry
Урок 14.4. Стратегия тегов