Как настроить частный реестр Docker на Ubuntu 22.04

Если вы работаете в организации и хотите хранить свои образы Docker у себя дома для быстрого развертывания, то хостинг частного репозитория Docker — идеальный вариант. Наличие частного реестра Docker позволяет вам владеть конвейером распространения образов и иметь более жесткий контроль над их хранением и распространением. Вы можете интегрировать свой реестр с системой CI/CD, что улучшит ваш рабочий процесс.

В этом руководстве мы расскажем вам, как настроить и использовать частный реестр Docker на сервере Ubuntu 22.04, используя Amazon S3 в качестве места хранения.

Предварительные условия

  • Два Linux-сервера с Ubuntu 22.04. Один сервер будет выступать в качестве хоста реестра, а другой будет использоваться в качестве клиента для отправки запросов и получения изображений с хоста.
  • Зарегистрированное доменное имя, указывающее на хост-сервер. Мы будем использовать registry.example.com для нашего учебника.
  • Пользователь, не являющийся root, с привилегиями sudo на обеих машинах.
  • Убедитесь, что все обновлено.
    $ sudo apt update
    $ sudo apt upgrade
    
  • Несколько пакетов, необходимых вашей системе.
    $ sudo apt install wget curl nano software-properties-common dirmngr apt-transport-https gnupg2 ca-certificates lsb-release ubuntu-keyring unzip -y
    

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

Шаг 1 — Настройка брандмауэра

Первым шагом будет настройка брандмауэра. По умолчанию Ubuntu поставляется с ufw (Uncomplicated Firewall).

Проверьте, запущен ли брандмауэр.

$ sudo ufw status

Вы должны получить следующий результат.

Status: inactive

Разрешите порт SSH, чтобы брандмауэр не разорвал текущее соединение при его включении.

$ sudo ufw allow OpenSSH

Разрешите также порты HTTP и HTTPS.

$ sudo ufw allow http
$ sudo ufw allow https

Включите брандмауэр

$ sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Еще раз проверьте состояние брандмауэра.

$ sudo ufw status

Вы должны увидеть аналогичный результат.

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443                        ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443 (v6)                   ALLOW       Anywhere (v6)

Шаг 2 — Установите Docker и Docker Compose

Этот шаг необходим как на сервере, так и на клиентских машинах.

Ubuntu 22.04 поставляется со старой версией Docker. Чтобы установить последнюю версию, сначала импортируйте ключ Docker GPG.

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

Создайте файл репозитория Docker.

$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Обновите список системных репозиториев.

$ sudo apt update

Установите последнюю версию Docker.

$ sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Убедитесь, что он запущен.

$ sudo systemctl status docker
? docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Thu 2023-04-13 09:37:09 UTC; 3min 47s ago
TriggeredBy: ? docker.socket
       Docs: https://docs.docker.com
   Main PID: 2106 (dockerd)
      Tasks: 7
     Memory: 26.0M
        CPU: 267ms
     CGroup: /system.slice/docker.service
             ??2106 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

По умолчанию Docker требует привилегий root. Если вы хотите избежать использования sudo каждый раз, когда вы запускаете docker , добавляйте свое имя пользователя в docker группу.

$ sudo usermod -aG docker $(whoami)

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

$ su - ${USER}

Убедитесь, что ваш пользователь добавлен в группу Docker.

$ groups
navjot wheel docker

Шаг 3 — Настройка реестра Docker

Создайте каталоги пользователей

Создайте каталог для конфигурации реестра.

$ mkdir ~/docker-registry

Переключитесь на docker-registry каталог.

$ cd ~/docker-registry

Создайте каталог для хранения пароля аутентификации HTTP, файлов конфигурации Nginx и сертификатов SSL.

$ mkdir auth

Создайте еще один каталог для хранения журналов Nginx.

$ mkdir logs

Создайте ведро Amazon S3

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

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

Создайте ведро со следующими настройками.

  • ACL должен быть отключен.
  • Публичный доступ к ведру должен быть отключен.
  • Версионность ведра должна быть отключена.
  • Включите шифрование ведра с помощью управляемых ключей Amazon S3. (SSE-S3)
  • Блокировка объектов должна быть отключена.

Создайте пользователя IAM со следующей политикой.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetBucketLocation",
        "s3:ListBucketMultipartUploads"
      ],
      "Resource": "arn:aws:s3:::S3_BUCKET_NAME"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:ListMultipartUploadParts",
        "s3:AbortMultipartUpload"
      ],
      "Resource": "arn:aws:s3:::S3_BUCKET_NAME/*"
    }
  ]
}

Замените S3_BUCKET_NAME на имя вашего ведра S3.

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

Создание файла Docker Compose

Создайте docker-compose.yml файл и откройте его для редактирования.

$ nano docker-compose.yml

Вставьте в него следующий код.

services:
  registry:
    image: registry:2
    restart: always
    environment:
      - REGISTRY_STORAGE=s3
      - REGISTRY_STORAGE_S3_REGION=us-west-2
      - REGISTRY_STORAGE_S3_BUCKET=hf-docker-registry
      - REGISTRY_STORAGE_S3_ENCRYPT=true
      - REGISTRY_STORAGE_S3_CHUNKSIZE=5242880
      - REGISTRY_STORAGE_S3_SECURE=true
      - REGISTRY_STORAGE_S3_ACCESSKEY=AKIA3FIG4NVFNXKQXMSJ
      - REGISTRY_STORAGE_S3_SECRETKEY=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
      - REGISTRY_STORAGE_S3_V4AUTH=true
      - REGISTRY_STORAGE_S3_ROOTDIRECTORY=/image-registry
      - REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR=inmemory
      - REGISTRY_HEALTH_STORAGEDRIVER_ENABLED=false
  nginx:
    image: "nginx:alpine"
    ports:
      - 443:443
    links:
      - registry:registry
    volumes:
      - ./auth:/etc/nginx/conf.d
      - ./auth/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./logs:/var/log/nginx
      - /etc/letsencrypt:/etc/letsencrypt

Сохраните файл, нажав кнопку Ctrl + X и ввести Y при появлении запроса.

Давайте пройдемся по тому, что мы настроили в нашем файле compose.

  1. Первым шагом будет захват последнего образа версии 2 реестра Docker из хаба. Мы не используем тег latest, потому что он может вызвать проблемы в случае серьезного обновления версии. Установив значение 2, вы сможете получить все обновления версии 2.x и при этом избежать автоматического обновления до следующей основной версии, что может привести к внесению изменений.
  2. Контейнер реестра настроен на постоянный перезапуск в случае сбоя или неожиданного отключения.
  3. Мы задали различные переменные окружения для хранилища Amazon S3. Давайте быстро пройдемся по ним.
    • REGISTRY_STORAGE задает тип хранилища. Мы выбрали s3 поскольку мы используем Amazon S3.
    • REGISTRY_STORAGE_S3_REGION устанавливает регион вашего ведра S3.
    • REGISTRY_STORAGE_S3_BUCKET задает имя вашего ведра S3.
    • REGISTRY_STORAGE_S3_ENCRYPT — установите значение true, если вы включили шифрование Bucket.
    • REGISTRY_STORAGE_S3_CHUNKSIZE устанавливает размер загружаемых фрагментов. Он должен быть больше 5 МБ (5 * 1024 * 1024).
    • REGISTRY_STORAGE_S3_SECURE — установите значение true, если вы собираетесь использовать HTTPS.
    • REGISTRY_STORAGE_S3_ACCESSKEY и REGISTRY_STORAGE_S3_SECRETKEY — Учетные данные пользователя, которые вы получили после создания пользователя IAM.
    • REGISTRY_STORAGE_S3_V4AUTH — Установите значение true, если вы используете v4 аутентификацию AWS. Если вы получаете ошибки, связанные с входом в S3, установите значение false.
    • REGISTRY_STORAGE_S3_ROOTDIRECTORY — задает корневой каталог в вашем ведре, в котором будут храниться данные реестра.
    • REGISTRY_STORAGE_CACHE_BLOBDESCRIPTOR — задает местоположение кэша. В нашем случае мы храним его в памяти. Вы также можете настроить его на использование Redis.
    • REGISTRY_HEALTH_STORAGEDRIVER_ENABLED — Установите значение false, чтобы отключить службу проверки состояния хранилища в реестре. В реестре есть ошибка, которая может вызвать проблемы, если не установить значение false.
  4. Реестр Docker взаимодействует через порт 5000, который мы открыли на нашем сервере для docker.
  5. ./auth:/etc/nginx/conf.d отображение гарантирует, что все настройки Nginx будут доступны в контейнере.
  6. ./auth/nginx.conf:/etc/nginx/nginx.conf:ro сопоставляет файл настроек Nginx из системы с файлом в контейнере в режиме только для чтения.
  7. ./logs:/var/log/nginx позволяет получить доступ к журналам Nginx в системе путем сопоставления с каталогом журналов Nginx в контейнере.
  8. Настройки реестра Docker хранятся в файле /etc/docker/registry/config.yml файле в контейнере, и мы сопоставили его с файлом config.yml файлу в текущем каталоге, который мы создадим на следующем шаге.

Настройка аутентификации

Чтобы настроить HTTP-аутентификацию, вам необходимо установить программу httpd-tools пакет.

$ sudo apt install apache2-utils -y

Создайте файл паролей в папке ~/docker-registry/auth каталоге.

$ htpasswd -Bc ~/docker-registry/auth/nginx.htpasswd user1
New password:
Re-type new password:
Adding password for user user1

The -c флаг указывает команде на создание нового файла, а флаг -B использовать алгоритм bcrypt, поддерживаемый Docker. Заменить user1 на имя пользователя по вашему выбору.

Если вы хотите добавить больше пользователей, выполните команду еще раз, но уже без -c флага.

$ htpasswd -B ~/docker-registry/auth/registry.password user2

Теперь файл будет сопоставлен с контейнером реестра для проверки подлинности.

Шаг 4 — Установка SSL

Нам нужно установить Certbot, чтобы сгенерировать SSL-сертификат. Вы можете установить Certbot из репозитория Ubuntu или взять последнюю версию с помощью инструмента Snapd. Мы будем использовать версию Snapd.

Ubuntu 22.04 поставляется с установленным по умолчанию Snapd. Выполните следующие команды, чтобы убедиться, что ваша версия Snapd актуальна.

$ sudo snap install core && sudo snap refresh core

Установите Certbot.

$ sudo snap install --classic certbot

Используйте следующую команду, чтобы убедиться, что команда Certbot может быть запущена, создав символическую ссылку на файл /usr/bin каталог.

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Выполните следующую команду, чтобы сгенерировать SSL-сертификат.

$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d registry.example.com

Приведенная выше команда загрузит сертификат на /etc/letsencrypt/live/registry.example.com каталог на вашем сервере.

Создайте группа Диффи-Хеллмана сертификат.

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

Проверьте службу планировщика обновления Certbot.

$ sudo systemctl list-timers

Вы найдете snap.certbot.renew.service как одну из запланированных к запуску служб.

NEXT                        LEFT          LAST                        PASSED        UNIT                      ACTIVATES
.....
Sun 2023-04-14 00:00:00 UTC 19min left    Sat 2023-02-25 18:04:05 UTC n/a          snap.certbot.renew.timer  snap.certbot.renew.service
Sun 2023-04-14 00:00:20 UTC 19min left    Sat 2023-02-25 10:49:23 UTC 14h ago      apt-daily-upgrade.timer   apt-daily-upgrade.service
Sun 2023-04-14 00:44:06 UTC 3h 22min left Sat 2023-02-25 20:58:06 UTC 7h ago       apt-daily.timer           apt-daily.service

Выполните пробный запуск процесса, чтобы убедиться, что обновление SSL работает нормально.

$ sudo certbot renew --dry-run

Если ошибок нет, все готово. Ваш сертификат обновится автоматически.

Скопируйте файл Dhparam в контейнер

Скопируйте файл Группа Диффи-Хеллмана сертификат на ~/docker-registry/auth каталог, который будет сопоставлен с контейнером.

$ sudo cp /etc/ssl/certs/dhparam.pem ~/docker-registry/auth

Шаг 5 — Настройка Nginx

Следующий шаг включает в себя настройку сервера Nginx в качестве внешнего прокси-сервера для сервера реестра Docker. Реестр Docker поставляется со встроенным сервером, работающим на порту 5000. Мы разместим его за Nginx.

Создайте и откройте файл ~/docker-registry/auth/nginx.conf для редактирования.

$ sudo nano ~/docker-registry/auth/nginx.conf

Вставьте в него следующий код.

events {
    worker_connections  1024;
}

http {

  upstream docker-registry {
    server registry:5000;
  }

  ## Set a variable to help us decide if we need to add the
  ## 'Docker-Distribution-Api-Version' header.
  ## The registry always sets this header.
  ## In the case of nginx performing auth, the header is unset
  ## since nginx is auth-ing before proxying.
  map $upstream_http_docker_distribution_api_version $docker_distribution_api_version {
    '' 'registry/2.0';
  }

  server {
    listen 443 ssl http2;
    server_name registry.example.com;

    # SSL
    ssl_certificate /etc/letsencrypt/live/registry.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/registry.example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/registry.example.com/chain.pem;

    access_log  /var/log/nginx/registry.access.log;
    error_log   /var/log/nginx/registry.error.log;

    # Recommendations from https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;
    ssl_ecdh_curve X25519:prime256v1:secp384r1:secp521r1;
    ssl_session_cache shared:SSL:10m;
    ssl_dhparam /etc/nginx/conf.d/dhparam.pem;
    resolver 8.8.8.8;

    # disable any limits to avoid HTTP 413 for large image uploads
    client_max_body_size 0;

    # required to avoid HTTP 411: see Issue #1486 (https://github.com/moby/moby/issues/1486)
    chunked_transfer_encoding on;

    location /v2/ {
      # Do not allow connections from docker 1.5 and earlier
      # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
      if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
        return 404;
      }

      # To add basic authentication to v2 use auth_basic setting.
      auth_basic "Registry realm";
      auth_basic_user_file /etc/nginx/conf.d/nginx.htpasswd;

      ## If $docker_distribution_api_version is empty, the header is not added.
      ## See the map directive above where this variable is defined.
      add_header 'Docker-Distribution-Api-Version' $docker_distribution_api_version always;

      proxy_pass                          http://docker-registry;
      proxy_set_header  Host              $http_host;   # required for docker client's sake
      proxy_set_header  X-Real-IP         $remote_addr; # pass on real client's IP
      proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
      proxy_set_header  X-Forwarded-Proto $scheme;
      proxy_read_timeout                  900;
    }
  }
}

Сохраните файл, нажав кнопку Ctrl + X и ввести Y при появлении соответствующего запроса.

Шаг 6 — Запуск реестра Docker

Перейдите в каталог реестра Docker.

$ cd ~/docker-registry

Запустите контейнер docker.

$ docker compose up -d

Проверьте состояние контейнеров.

$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED              STATUS              PORTS                                      NAMES
3328b7e36bb2   nginx:alpine   "/docker-entrypoint.…"   About a minute ago   Up 3 seconds        80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   docker-registry-nginx-1
bf7cdfc0e013   registry:2     "/entrypoint.sh /etc…"   About a minute ago   Up About a minute   5000/tcp                                 docker-registry-registry-1

Войдите в реестр Docker.

$ docker login -u=user1 -p=password https://registry.example.com

Вы получите следующий результат.

WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /home/username/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

Вы также можете открыть URL https://registry.example.com/v2/ в браузере, и он запросит имя пользователя и пароль. Вы должны увидеть пустую страницу с {} на нем.

Вы можете проверить URL на терминале, используя curl.

$ curl -u user1 -X GET https://registry.example.com/v2/
Enter host password for user 'user1':
{}

Загрузите последний докер-образ Ubuntu.

$ docker pull ubuntu:latest

Пометьте этот образ для частного реестра.

$ docker tag ubuntu:latest registry.example.com/ubuntu2204

Поместите изображение в реестр.

$ docker push registry.example.com/ubuntu2204

Проверьте, успешно ли прошло перемещение.

$ curl -u user1 -X GET https://registry.example.com/v2/_catalog
Enter host password for user 'user1':
{"repositories":["ubuntu2204"]}

Введите пароль аутентификации Nginx, когда появится запрос, и вы увидите список репозиториев, доступных через реестр.

Выйдите из системы с помощью терминала, чтобы очистить учетные данные.

$ docker logout https://registry.example.com
Removing login credentials for registry.example.com

Проверьте список образов Docker, доступных для использования в данный момент.

$ docker images
REPOSITORY                            TAG       IMAGE ID       CREATED       SIZE
registry                             2         8db46f9d7550   2 weeks ago   24.2MB
nginx                                alpine    8e75cbc5b25c   2 weeks ago   41MB
ubuntu                               latest    08d22c0ceb15   5 weeks ago   77.8MB
registry.example.com/ubuntu2204      latest    08d22c0ceb15   5 weeks ago   77.8MB

Шаг 7 — Доступ и использование реестра Docker с клиентской машины

Войдите на клиент-сервер. В шаге 1 мы установили Docker на клиентской машине.

Войдите в частный реестр Docker с клиентской машины.

$ docker login -u=user1 -p=password https://registry.example.com

Извлеките образ Ubuntu из реестра.

$ docker pull registry.example.com/ubuntu2204

Перечислите все образы на клиентской машине.

$ docker images
REPOSITORY                        TAG        IMAGE ID       CREATED         SIZE
registry.example.com/ubuntu2204   latest     08d22c0ceb15   5 weeks ago   77.8MB

Создайте и запустите контейнер, используя загруженный образ.

$ docker run -it registry.example.com/ubuntu2204 /bin/bash

Вы войдете в оболочку внутри контейнера Ubuntu.

root@647899f255db:

Выполните следующую команду, чтобы проверить версию Linux.

root@a2da49fdbea9$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.2 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.2 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy

Теперь вы можете начать использовать реестр Docker с клиентских машин.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *