Контейнерный регистр – это каталог хранения, откуда можно за pulls и push контейнерных образов.

У разработчиков доступны множество публичных и частных регистров, таких как Docker Hub, Amazon ECR и Google Cloud Artifact Registry. Но иногда вместо того, чтобы полагаться на внешнего поставщика, может потребоваться самостоятельно разместить ваши образы. Это дает вам больше контроля над конфигурацией регистра и местом размещения контейнерных образов.

В этой статье мы рассмотрим практический指南 по тому, как самостоятельно разместить Container Registry.

Contents

Вы будете извлекать максимум из этой статьи, если у вас уже есть опыт работы с такими инструментами, как Docker и NGINX, и генеральное понимание того, что за контейнер.

Что такое контейнерная картинка?

Перед тем, как мы поговорим о контейнерных регистрах, посмотрим, что такое контейнерная картинка.简而言之, контейнерная картинка – это пакет, который содержит все файлы, библиотеки и настройки для запуска контейнера. Она состоит из слоев, где каждый слой представляет собой набор изменений файловой системы, добавляющих, удаляющих или изменяющих файлы.

Самый обычный способ создания контейнерной картинки – это использование Dockerfile.

# build an image
docker build -t pliutau/hello-world:v0 .

# check the images locally
docker images
# REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
# hello-world   latest    9facd12bbcdd   22 seconds ago   11MB

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

Что такое реестр контейнеров?

Реестр контейнеров – это каталог хранения, из которого можно извлекать и перемещать образы контейнеров. Образы группируются в репозитории, которые представляют собой коллекции связанных образов с одинаковым именем. Например, в реестре Docker Hub nginx – это имя репозитория, содержащего различные версии образов NGINX.

Некоторые реестры являются публичными, то есть образы, размещенные в них, доступны всем желающим в Интернете. Публичные реестры, такие как Docker Hub, являются хорошим вариантом для размещения проектов с открытым исходным кодом.

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

Растет список доступных частных реестров, таких как Amazon ECR, GCP Artifact Registry, GitHub Container Registry, а Docker Hub также предлагает функцию частного репозитория.

Как разработчик, вы взаимодействуете с реестром контейнеров при использовании команд docker push и docker pull.

docker push docker.io/pliutau/hello-world:v0

# В случае Docker Hub мы можем пропустить часть с реестром
docker push pliutau/hello-world:v0

Давайте рассмотрим анатомию URL-адреса образа контейнера:

docker pull docker.io/pliutau/hello-world:v0@sha256:dc11b2...
                |            |            |          |
                ↓            ↓            ↓          ↓
             registry    repository      tag       digest

Почему вы можете захотеть самостоятельно разместить реестр контейнеров

Иногда, вместо того чтобы полагаться на провайдера вроде AWS или GCP, вы можете захотеть разместить свои образы самостоятельно. Это позволит сохранить внутреннюю инфраструктуру и меньше зависеть от внешних поставщиков. В некоторых отраслях с жестким регулированием это даже является обязательным требованием.

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

Как самостоятельно разместить реестр контейнеров

Существует несколько решений для создания реестра контейнеров с открытым исходным кодом. Наиболее популярное из них официально поддерживается Docker и называется registry, с его реализацией для хранения и распространения образов и артефактов контейнеров. Это означает, что вы можете запустить свой собственный реестр внутри контейнера.

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

  • Установите Docker и Docker Compose на сервере.

  • Настройте и запустите контейнер registry.

  • Запустите NGINX для обработки TLS и пересылки запросов к контейнеру реестра.

  • Установите SSL-сертификаты и настройте домен.

Шаг 1: Установите Docker и Docker Compose на сервер

Вы можете использовать любой сервер, поддерживающий Docker. Например, вы можете использовать DigitalOcean Droplet с Ubuntu. Для этой демонстрации я использовал Google Cloud Compute для создания виртуальной машины с Ubuntu.

neofetch

# OS: Ubuntu 20.04.6 LTS x86_64
# CPU: Intel Xeon (2) @ 2.200GHz
# Память: 3908MiB

После того, как мы окажемся внутри нашей ВМ, мы должны установить Docker и Docker Compose. Docker Compose необязателен, но он облегчает управление многоконтейнерными приложениями.

# install docker engine and docker-compose
sudo snap install docker

# verify the installation
docker --version
docker-compose --version

Step 2: Configure and run the registry container

Следующим шагом нам нужно настроить наш контейнер реестра. Следующий файл compose.yaml создаст контейнер реестра с томом для хранения образов и томом для хранения файла паролей.

services:
  registry:
    image: registry:latest
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      # Mount the password file
      - ./registry/registry.password:/auth/registry.password
      # Mount the data directory
      - ./registry/data:/data
    ports:
      - 5000

The password file defined in REGISTRY_AUTH_HTPASSWD_PATH is used to authenticate users when they push or pull images from the registry. We should create a password file using the htpasswd command. We should also create a folder for storing the images.

mkdir -p ./registry/data

# install htpasswd
sudo apt install apache2-utils

# create a password file. username: busy, password: bee
htpasswd -Bbn busy bee > ./registry/registry.password

Now we can start the registry container. If you see this message, than everything is working as it should:

docker-compose up

# successfull run should output something like this:
# registry | level=info msg="listening on [::]:5000"

Step 3: Run NGINX for handling TLS

As mentioned earlier, we can use NGINX to handle TLS and forward requests to the registry container.

The Docker Registry requires a valid trusted SSL certificate to work. You can use something like Let’s Encrypt or obtain it manually. Make sure you have a domain name pointing to your server (registry.pliutau.com in my case). For this demo I already obtained the certificates using certbot and put it in the ./nginx/certs directory.

Рассмотрим, как мы можем запустить NGINX в контейнере, добавив следующий сервис в файл compose.yaml:

services:
  registry:
    # ...
  nginx:
    image: nginx:latest
    depends_on:
      - registry
    volumes:
      # mount the nginx configuration
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      # mount the certificates obtained from Let's Encrypt
      - ./nginx/certs:/etc/nginx/certs
    ports:
      - "443:443"

Наш файл nginx.conf может выглядеть следующим образом:

worker_processes auto;

events {
    worker_connections 1024;
}

http {
    upstream registry {
        server registry:5000;
    }

    server {
        server_name registry.pliutau.com;
        listen 443 ssl;

        ssl_certificate /etc/nginx/certs/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/privkey.pem;

        location / {
            # important setting for large images
            client_max_body_size                1000m;

            proxy_pass                          http://registry;
            proxy_set_header  Host              $http_host;
            proxy_set_header  X-Real-IP         $remote_addr;
            proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header  X-Forwarded-Proto $scheme;
            proxy_read_timeout                  900;
        }
    }
}

Готово к работе!

После этих шагов мы можем запустить контейнеры регистра и Nginx.

docker-compose up

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

docker login registry.pliutau.com

# Username: busy
# Password: bee
# Login Succeeded

Время построить и отправить наш образ на нашу самому себе hosted registry:

docker build -t registry.pliutau.com/pliutau/hello-world:v0 .

docker push registry.pliutau.com/pliutau/hello-world:v0
# v0: digest: sha256:a56ea4... size: 738

На вашем сервере вы можете проверить загруженные образы в папке data:

ls -la ./registry/data/docker/registry/v2/repositories/

Другие опции

Пример, приведенный выше, также показывает, как можно запустить регистр на Kubernetes. Также вы можете использовать управляемую службу регистра, такую как Harbor, который является открытым источником регистра, обеспечивающим продвиженные функции безопасности и совместимый с Docker и Kubernetes.

Также, если вы хотите иметь UI для вашего самомунтированного регистра, вы можете использовать проект, такой как joxit/docker-registry-ui, и запустить его в отдельном контейнере.

Заключение

Самомунтированные контейнерные регистры позволяют вам иметь полный контроль над вашим регистром и способом его развертывания. В то же время это сопровождение и безопасность регистра.

不论您运行自托管注册表的原因是什么,现在您知道它是如何操作的。从这您可以比较不同的选项并选择最适合您需求的那个。

您可以在这个演示的完整源代码在 GitHub 上找到。此外,您可以在 我们的YouTube频道 上观看视频。