Создание локального Docker Registry — пошаговая инструкция.

Мы уже научились использовать образы и модифицировать их под свои нужды. А как их хранить и передавать своим коллегам? Через  Docker Registry. Сегодня мы разберемся, как развернуть локальный Docker реестр.

Он поможет вам хранить, управлять и распространять образы контейнеров внутри вашей команды без необходимости постоянного обращения к публичным реестрам.

Пару слов об окружении:

В рамках данной статьи, Docker Registry будет запущен на хосте в локальной сети, без использования SSL сертификата и https. Чтобы Docker мог обращаться к такому реестру его надо внести в файл daemon.json (локация варьируется в зависимости от ОС).

В нашем случае файл /etc/docker/daemon.json имеет следующий вид (используйте IP вашего хоста):

{ "insecure-registries":["192.168.0.114:5000"] }

И перезапустить Docker:

[root@waky ~]# systemctl restart docker
[root@waky ~]#

Шаг 1: Запуск Docker Registry в контейнере

Самый простой способ — это использовать официальный образ Docker Registry. Выполните следующую команду для запуска Registry:

[root@waky ~]# docker run -d -p 5000:5000 --name local-registry registry:3
Unable to find image 'registry:3' locally
3: Pulling from library/registry
f637881d1138: Pull complete
ed8e0977a7e0: Pull complete
9fc4080776f9: Pull complete
1a51344b3dd0: Pull complete
658f32c91179: Pull complete
Digest: sha256:cd92709b4191c5779cd7215ccd695db6c54652e7a62843197e367427efb84d0e
Status: Downloaded newer image for registry:3
d2db9d1e681a1b5a34925106fa0bf768362e270f7812c821e3340771c6faabbf
[root@waky ~]#

Использованные параметры:

-d — запуск в фоновом режиме
-p 5000:5000 — проброс порта 5000, чтобы обращаться к Registry через IP-адрес или localhost
–name local-registry — имя контейнера для удобства
registry:3 — версия Docker Registry

После выполнения команды у вас будет запущен локальный Registry, доступный по адресу:

http://<ваш_IP>:5000

В моем случае это:

http:// 192.168.0.114:5000

Шаг 2: Тегирование и отправка образов в Registry

Если у вас уже есть кастомный образ, который вы хотите поместить в реестр, можете использовать его. Мы же создадим новый образ, с помощью простого Dockerfile следующего содержания:

FROM alpine:latest
RUN apk add wget

За основу мы берем образ alpine и устанавливаем утилиту wget, если вы не знакомы с использованием  Dockerfile, вы найдете подробности в статье об образах.

Командой build мы собираем образ из Dockerfile находящегося в текущей (./) директории:

[root@waky my-app]# docker build -t my-app ./
[+] Building 6.1s (6/6) FINISHED
docker:default
 => [internal] load build definition from Dockerfile
0.1s
 => => transferring dockerfile: 133B
0.0s
 => [internal] load metadata for docker.io/library/alpine:latest
0.0s
 => [internal] load .dockerignore
0.0s
 => => transferring context: 2B
0.0s
 => CACHED [1/2] FROM docker.io/library/alpine:latest
0.0s
 => [2/2] RUN apk add wget
5.1s
 => exporting to image
0.4s
 => => exporting layers
0.3s
 => => writing image sha256:8e5ddd9894ab6f71a38606884f795af7d83ad5305626b4bd6a7e3a5f7179babc
0.0s
 => => naming to docker.io/library/my-app
0.0s
[root@waky my-app]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
my-app       latest    8e5ddd9894ab   13 seconds ago   14.2MB
nginx        latest    d261fd19cb63   2 days ago       152MB
alpine       latest    706db57fb206   4 weeks ago      8.32MB
registry     3         e4e570676819   7 months ago     57.7MB
[root@waky my-app]#

Наш новый образ my-app появился в списке.

Добавим этому образу новый тег (команда tag), не забудьте указать свой IP:

[root@waky my-app]# docker tag my-app 192.168.0.114:5000/my-app
[root@waky my-app]# docker images
REPOSITORY                  TAG       IMAGE ID       CREATED          SIZE
192.168.0.114:5000/my-app   latest    8e5ddd9894ab   12 minutes ago   14.2MB
my-app                      latest    8e5ddd9894ab   12 minutes ago   14.2MB
nginx                       latest    d261fd19cb63   2 days ago       152MB
alpine                      latest    706db57fb206   4 weeks ago      8.32MB
registry                    3         e4e570676819   7 months ago     57.7MB
[root@waky my-app]#

Использованные параметры:

my-app – имя образа которому присваивается тег
192.168.0.114:5000/my-app – новый тег, по шаблону IP_хоста:порт/имя образа

В моем случае хост на котором я запустил локальный реестр имеет адрес 192.168.0.114, а порт при запуске контейнера с Docker Registry мы указали 5000.

Теперь отправим образ в локальный Docker Registry:

[root@waky my-app]# docker push 192.168.0.114:5000/my-app
Using default tag: latest
The push refers to repository [192.168.0.114:5000/my-app]
4bc8b0b331f1: Pushed
256f393e029f: Pushed
latest: digest: sha256:9e2e247248398e24153bd7fba9c5286a631963d9d7b6337f47f3d2ca4fc2d86d size: 738
[root@waky my-app]#

Образ успешно загрузился, и будет храниться у вас в локальном Registry.

Можем проверить образа в локальном реестре с помощью curl:

[root@waky my-app]# curl http://localhost:5000/v2/_catalog
{"repositories":["my-app"]}
[root@waky my-app]#

Если вы столкнулись с ошибкой вида:

http: server gave HTTP response to HTTPS client

перепроверьте, правильно ли вы добавили реестр в файл daemon.json

Шаг 3: Использование образов из локального Registry

Удалим образа из нашего локального Docker, чтобы убедиться что они будут подгружаться из Registry:

[root@waky my-app]# docker rmi my-app 192.168.0.114:5000/my-app
Untagged: my-app:latest
Untagged: 192.168.0.114:5000/my-app:latest
Untagged: 192.168.0.114:5000/my-app@sha256:9e2e247248398e24153bd7fba9c5286a631963d9d7b6337f47f3d2ca4fc2d86d
Deleted: sha256:8e5ddd9894ab6f71a38606884f795af7d83ad5305626b4bd6a7e3a5f7179babc
[root@waky my-app]#

Запустим контейнер из образа, который хранится в нашем Registry:

[root@waky my-app]# docker run -td --name my_container 192.168.0.114:5000/my-app /bin/sh
Unable to find image '192.168.0.114:5000/my-app:latest' locally
latest: Pulling from my-app
2d35ebdb57d9: Already exists
140a5e68c1f2: Already exists
Digest: sha256:9e2e247248398e24153bd7fba9c5286a631963d9d7b6337f47f3d2ca4fc2d86d
Status: Downloaded newer image for 192.168.0.114:5000/my-app:latest
a3c48eaf675fe9f59a64ddd701a0ad82590a840ee716678cdfbdabdd0406f874
[root@waky my-app]# docker images
REPOSITORY                  TAG       IMAGE ID       CREATED             SIZE
192.168.0.114:5000/my-app   latest    8e5ddd9894ab   About an hour ago   14.2MB
nginx                       latest    d261fd19cb63   2 days ago          152MB
alpine                      latest    706db57fb206   4 weeks ago         8.32MB
registry                    3         e4e570676819   7 months ago        57.7MB
[root@waky my-app]#

Docker не нашел запрашиваемый образ локально и выкачал его из нашего собственного хранилища.

Мы успешно настроили и проверили работу локального Docker Registry.

Шаг 4: Подключение к Docker Registry с другого хоста

На прошлых этапах все действия осуществлялись в рамках одного хоста, давайте попробуем подключиться к нашему Docker Registry, например, с нашего рабочего ПК.

Ранее на него мы установили Docker Desktop. Перед запуском Docker надо внести изменения в файл daemon.json

В моем случае это:

C:\Users\waky\.docker\daemon.json

где С – диск на котором установлена система, waky – имя пользователя

Соблюдая синтаксис json добавьте директиву “insecure-registries”, в моем случае содержимое файла выглядит так:

{
  "builder": {
    "gc": {
      "defaultKeepStorage": "20GB",
      "enabled": true
    }
  },
  "experimental": false,
  "insecure-registries": [
    "192.168.0.114:5000"
  ]
}

192.168.0.114 – адрес хоста с реестром (замените на свой)

После сохраняем файл и запускаем/перезапускаем Docker Desktop.

Когда запустится Docker, открываем командную панель и выполняем ту же самую команду, что и на 3 шаге:

docker run -td --name my_container 192.168.0.114:5000/my-app /bin/sh

Программа обратиться к Docker Registry работающем на хосте с указанным IP, скачает образ и запустит контейнер из него.

Если на этапе подключения к реестру вы столкнулись с таймаутом, вероятнее всего вас блокирует файрвол. Убедитесь, что на принимающем хосте открыт доступ до порта 5000.

Шаг 5: Безопасность работы Registry

Мы рассмотрели упрощенный вариант использования Docker Registry. Его использование в таком виде возможно в локальных сетях без постороннего доступа.

В реальности же вы вряд ли захотите, чтобы ваш личный реестр образов был доступен без ограничений.

По умолчанию, Registry работает без защиты, работает по HTTP и не требует авторизации.

Для использования в закрытой сети это может быть приемлемо, но для производства рекомендуется настроить:

  • TLS (SSL) — для шифрования трафика
  • Аутентификацию — для ограничения доступа
  • Файрвол – для ограничения трафика по IP

Эти настройки требуют генерации сертификатов и дополнительных конфигураций и заслуживают отдельной большой статьи.

Заключение

Теперь у вас есть полностью подготовленный и работающий локальный Docker Registry, который упростит вашу работу с образами и их передачу.

Это отличный шаг в развитии инфраструктуры контейнеризации в вашей среде.