Если вы работаете в организации и хотите хранить свои образы 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.
- Первым шагом будет захват последнего образа версии 2 реестра Docker из хаба. Мы не используем тег latest, потому что он может вызвать проблемы в случае серьезного обновления версии. Установив значение 2, вы сможете получить все обновления версии 2.x и при этом избежать автоматического обновления до следующей основной версии, что может привести к внесению изменений.
- Контейнер реестра настроен на постоянный перезапуск в случае сбоя или неожиданного отключения.
- Мы задали различные переменные окружения для хранилища 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.
- Реестр Docker взаимодействует через порт 5000, который мы открыли на нашем сервере для docker.
./auth:/etc/nginx/conf.dотображение гарантирует, что все настройки Nginx будут доступны в контейнере../auth/nginx.conf:/etc/nginx/nginx.conf:roсопоставляет файл настроек Nginx из системы с файлом в контейнере в режиме только для чтения../logs:/var/log/nginxпозволяет получить доступ к журналам Nginx в системе путем сопоставления с каталогом журналов Nginx в контейнере.- Настройки реестра 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 с клиентских машин.