Как настроить частный реестр Docker в Ubuntu 22.04
Автор выбрал программу Write for DOnations.
Введение
TravisCI для беспрепятственного обновления изображений во время производства и разработки.
Docker Hub — это бесплатный общедоступный реестр, в котором могут размещаться ваши собственные образы Docker, но бывают ситуации, когда вы не хотите, чтобы ваш образ был общедоступным. Образы обычно содержат весь код, необходимый для запуска приложения, поэтому использование частного реестра может быть предпочтительнее при использовании проприетарного программного обеспечения.
В этом руководстве вы настроите и защитите свой собственный реестр Docker. Вы будете использовать Docker Compose для определения конфигураций, запускающих ваши контейнеры Docker, и Nginx для перенаправления трафика сервера из Интернета в работающий контейнер Docker. После того, как вы закончите это руководство, вы сможете отправить пользовательский образ Docker в свой частный реестр и безопасно извлечь образ с удаленного сервера.
Предпосылки
Для выполнения этого урока вам потребуется следующее:
- Два сервера Ubuntu 22.04 настроены в соответствии с Руководством по первоначальной настройке сервера Ubuntu 22.04, включая пользователя без полномочий root
sudo
и брандмауэр. На одном сервере будет размещаться ваш частный реестр Docker, а другой будет вашим клиентским сервером. - На обоих серверах установлен Docker, который можно настроить, выполнив шаги 1 и 2 раздела Установка и использование Docker в Ubuntu 22.04.
На хост-сервере вам нужно будет настроить:
- Docker Compose установлен на хост-сервере, который можно настроить, выполнив шаг 1 инструкции по установке и использованию Docker Compose в Ubuntu 22.04.
- Nginx установлен на вашем хост-сервере, который вы можете настроить, выполнив действия, описанные в разделе Как установить Nginx в Ubuntu 22.04.
- Nginx защищен с помощью Let’s Encrypt на вашем хост-сервере для частного реестра Docker, который вы можете настроить, следуя руководству Как защитить Nginx с помощью Let’s Encrypt в Ubuntu 22.04. Обязательно перенаправьте весь трафик с HTTP на HTTPS на шаге 4.
- Зарегистрированное доменное имя, которое разрешается в сервер, который вы используете для размещения частного реестра Docker. Вы настроите это как часть предварительного условия Let’s Encrypt. В этом руководстве мы будем называть его
your_domain
.
Шаг 1 — Установка и настройка реестра Docker
Запуск Docker из командной строки полезен при запуске и тестировании контейнеров, но он может стать громоздким при больших развертываниях, включающих несколько параллельно работающих контейнеров.
С Docker Compose вы пишете один файл
.yml
для настройки конфигурации каждого контейнера и информации, необходимой контейнерам для связи друг с другом. Вы можете использовать инструментdocker compose
, чтобы выдавать команды всем компонентам, составляющим ваше приложение, и управлять ими как группой.Docker Registry сам по себе является приложением с несколькими компонентами, поэтому для управления им вы будете использовать Docker Compose. Чтобы запустить экземпляр реестра, вы настроите файл
docker-compose.yml
, чтобы определить его и место на диске, где ваш реестр будет хранить свои данные.Вы сохраните конфигурацию в каталоге с именем
docker-registry
на хост-сервере. Создайте его, запустив:- mkdir ~/docker-registry
Перейдите к нему:
- cd ~/docker-registry
Затем создайте подкаталог с именем
data
, где ваш реестр будет хранить свои изображения:- mkdir data
Создайте и откройте файл с именем
docker-compose.yml
, выполнив:- nano docker-compose.yml
Добавьте следующие строки, которые определяют базовый экземпляр реестра Docker:
version: '3' services: registry: image: registry:latest ports: - "5000:5000" environment: REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data volumes: - ./data:/data
Сначала вы назначаете имя первой службы
registry
и устанавливаете ее образ вregistry
, используя последнюю версию. Затем в разделеports
вы сопоставляете порт5000
на хосте с портом5000
контейнера, что позволит вам отправить запрос на порт5000
на сервере и перенаправьте запрос в реестр.В разделе
environment
вы устанавливаете для переменнойREGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
значение/data
, указывая, в каком томе он должен хранить свои данные. Затем в разделеvolumes
вы сопоставляете каталог/data
в файловой системе хоста с/data
в контейнере, который действует как пройти через. Фактически данные будут храниться в файловой системе хоста.Сохраните и закройте файл.
Теперь вы можете начать настройку, выполнив:
- docker compose up
Контейнер реестра и его зависимости будут загружены и запущены.
Output[+] Running 2/2 ⠿ Network docker-registry_default Created 0.1s ⠿ Container docker-registry-registry-1 Created 0.1s Attaching to docker-registry-registry-1 docker-registry-registry-1 | time="2022-11-19T14:31:20.40444638Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown" docker-registry-registry-1 | time="2022-11-19T14:31:20.404960549Z" level=info msg="redis not configured" go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown" docker-registry-registry-1 | time="2022-11-19T14:31:20.412312462Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown" docker-registry-registry-1 | time="2022-11-19T14:31:20.412803878Z" level=info msg="Starting upload purge in 52m0s" go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown" docker-registry-registry-1 | time="2022-11-19T14:31:20.41296431Z" level=info msg="listening on [::]:5000" go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown" ...Далее в этом руководстве вы вернетесь к предупреждающему сообщению
Нет секрета HTTP
.Последняя строка вывода указывает на то, что он успешно запущен, прослушивая порт
5000
.Вы можете нажать
CTRL+C
, чтобы остановить его выполнение.На этом шаге вы создали конфигурацию Docker Compose, которая запускает реестр Docker, прослушивающий порт
5000
. На следующих шагах вы откроете его в своем домене и настроите аутентификацию.Шаг 2 — Настройка переадресации портов Nginx
В рамках предварительных условий вы включили HTTPS в своем домене. Чтобы открыть доступ к вашему защищенному реестру Docker, вам нужно настроить Nginx для перенаправления трафика из вашего домена в контейнер реестра.
Вы уже настроили файл
/etc/nginx/sites-available/your_domain
, содержащий конфигурацию вашего сервера. Откройте его для редактирования, запустив:- sudo nano /etc/nginx/sites-available/your_domain
Найдите существующий блок
location
:... location / { ... } ...
Вам необходимо перенаправить трафик на порт
5000
, где ваш реестр будет прослушивать трафик. Вы также хотите добавить заголовки к запросу, пересылаемому в реестр, который предоставляет дополнительную информацию от сервера о самом запросе. Замените существующее содержимое блокаlocation
следующими строками:... location / { # 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; } proxy_pass http://localhost:5000; 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; } ...
Блок
if
проверяет пользовательский агент запроса и проверяет, что версия клиента Docker выше 1.5 и что это не приложениеGo
, которое пытается получить доступ. Дополнительные пояснения по этому поводу вы можете найти в конфигурации заголовкаnginx
в руководстве Docker по реестру Nginx.Сохраните и закройте файл, когда закончите. Примените изменения, перезапустив Nginx:
- sudo systemctl restart nginx
Если вы получили сообщение об ошибке, дважды проверьте добавленную вами конфигурацию.
Чтобы убедиться, что Nginx правильно перенаправляет трафик в ваш контейнер реестра через порт
5000
, запустите его:- docker compose up
Затем в окне браузера перейдите в свой домен и получите доступ к конечной точке
v2
, например:https://your_domain/v2
Браузер загрузит пустой объект JSON:
{}
В вашем терминале вы получите вывод, подобный следующему:
Outputdocker-registry-registry-1 | time="2022-11-19T14:32:50.082396361Z" level=info msg="response completed" go.version=go1.16.15 http.request.host=your_domain http.request.id=779fe265-1a7c-4a15-8ae4-eeb5fc35de98 http.request.method=GET http.request.remoteaddr=87.116.166.89 http.request.uri="/v2" http.request.useragent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36" http.response.contenttype="text/html; charset=utf-8" http.response.duration="162.546µs" http.response.status=301 http.response.written=39 docker-registry-registry-1 | 172.19.0.1 - - [19/Nov/2022:14:32:50 +0000] "GET /v2 HTTP/1.0" 301 39 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36" docker-registry-registry-1 | 172.19.0.1 - - [19/Nov/2022:14:32:50 +0000] "GET /v2/ HTTP/1.0" 200 2 "" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36" docker-registry-registry-1 | time="2022-11-19T14:32:50.132472674Z" level=info msg="response completed" go.version=go1.16.15 http.request.host=your_domain http.request.id=0ffb17f0-c2a0-49d6-94f3-af046cfb96e5 http.request.method=GET http.request.remoteaddr=87.116.166.89 http.request.uri="/v2/" http.request.useragent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36" http.response.contenttype="application/json; charset=utf-8" http.response.duration=2.429608ms http.response.status=200 http.response.written=2 docker-registry-registry-1 | 172.19.0.1 - - [19/Nov/2022:14:32:50 +0000] "GET /favicon.ico HTTP/1.0" 404 19 "your_domain/v2/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36"Из последней строки вы знаете, что запрос
GET
был отправлен в/v2/
, которая является конечной точкой, на которую вы отправили запрос. Контейнер получил запрос, который вы сделали из-за переадресации портов, и вернул ответ{}
. Код200
означает, что контейнер успешно обработал запрос.Нажмите
CTRL+C
, чтобы остановить его выполнение.Теперь, когда вы настроили переадресацию портов, вы повысите безопасность своего реестра.
Шаг 3 — Настройка аутентификации
Nginx позволяет вам настроить HTTP-аутентификацию для управляемых им сайтов, которую вы можете использовать для ограничения доступа к вашему реестру Docker. Для этого вы создадите файл аутентификации с помощью
htpasswd
и добавите в него комбинации имени пользователя и пароля, которые будут приняты. Этот процесс включит аутентификацию в вашем реестре.Вы можете получить утилиту
htpasswd
, установив пакетapache2-utils
. Сделайте это, запустив:- sudo apt install apache2-utils -y
Вы сохраните файл аутентификации с учетными данными в папке
~/docker-registry/auth
. Создайте его, запустив:- mkdir ~/docker-registry/auth
Перейдите к нему:
- cd ~/docker-registry/auth
Создайте первого пользователя, заменив
username
на имя пользователя, которое вы хотите использовать. Флаг-B
указывает на использование алгоритмаbcrypt
, который требуется Docker:- htpasswd -Bc registry.password username
Введите пароль при появлении запроса. Комбинация учетных данных будет добавлена к
registry.password
.Примечание. Чтобы добавить больше пользователей, повторно запустите предыдущую команду без
-c
:- htpasswd -B registry.password username
-c
создает новый файл, поэтому его удаление приведет к обновлению существующего файла.Теперь, когда список учетных данных составлен, вы отредактируете
docker-compose.yml
, чтобы Docker использовал созданный вами файл для аутентификации пользователей. Откройте его для редактирования:- nano ~/docker-registry/docker-compose.yml
Добавьте выделенные строки:
version: '3' services: registry: image: registry:latest ports: - "5000:5000" environment: REGISTRY_AUTH: htpasswd REGISTRY_AUTH_HTPASSWD_REALM: Registry REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data volumes: - ./auth:/auth - ./data:/data
Вы добавили переменные среды, которые определяют использование HTTP-аутентификации и предоставляют путь к созданному файлу
htpasswd
. ДляREGISTRY_AUTH
вы указалиhtpasswd
в качестве значения, которое является используемой схемой аутентификации, и задали дляREGISTRY_AUTH_HTPASSWD_PATH
путь к файлу аутентификации. .REGISTRY_AUTH_HTPASSWD_REALM
означает имя областиhtpasswd
.Вы также смонтировали каталог
./auth
, чтобы сделать файл доступным внутри контейнера реестра. Сохраните и закройте файл.Теперь вы можете убедиться, что ваша аутентификация работает правильно. Сначала перейдите в основной каталог:
- cd ~/docker-registry
Затем запустите реестр, выполнив:
- docker compose up
В браузере обновите страницу своего домена. Вас попросят ввести имя пользователя и пароль.
После предоставления действительной комбинации учетных данных вы получите доступ к странице с пустым объектом JSON:
{}
Вы успешно прошли аутентификацию и получили доступ к реестру. Выйдите, нажав
CTRL+C
в терминале.Теперь ваш реестр защищен и доступен только после аутентификации. Затем вы настроите его для работы в качестве фонового процесса, сохраняя при этом устойчивость к перезагрузкам за счет автоматического запуска.
Шаг 4 — Запуск Docker Registry как службы
Вы можете убедиться, что контейнер реестра запускается каждый раз при загрузке системы или после ее сбоя, указав Docker Compose всегда поддерживать его работу.
Откройте
docker-compose.yml
для редактирования:- nano docker-compose.yml
Добавьте следующую строку в блок
registry
:... registry: restart: always ...
Установка для
restart
значенияalways
гарантирует, что контейнер выдержит перезагрузку. Когда вы закончите, сохраните и закройте файл.Теперь вы можете запустить свой реестр как фоновый процесс, передав
-d
:- docker compose up -d
Когда ваш реестр работает в фоновом режиме, вы можете свободно закрыть этот сеанс SSH, терминал и реестр не будут затронуты.
Поскольку образы Docker могут быть очень большими, вы затем увеличите максимальный размер файла, который Nginx будет принимать для загрузки.
Шаг 5 — Увеличение размера загружаемого файла для Nginx
Прежде чем отправлять образ в реестр, необходимо убедиться, что ваш реестр сможет обрабатывать загрузку больших файлов. Ограничение размера загружаемых файлов по умолчанию в Nginx составляет
1m
, чего недостаточно для образов Docker. Чтобы поднять его, вы измените основной файл конфигурации Nginx, расположенный в/etc/nginx/nginx.conf
.Откройте его для редактирования:
- sudo nano /etc/nginx/nginx.conf
Добавьте выделенную строку в раздел
http
:... http { client_max_body_size 16384m; ... } ...
Параметр
client_max_body_size
теперь имеет значение16384m
, что делает максимальный размер загрузки равным 16 ГБ.Сохраните и закройте файл.
Перезапустите Nginx, чтобы применить изменения конфигурации:
- sudo systemctl restart nginx
На этом шаге вы обновили размер файла, разрешенный Nginx. Теперь вы можете загружать большие образы в свой реестр Docker, при этом Nginx не блокирует передачу или не выдает ошибку.
Шаг 6 — Публикация в вашем личном реестре Docker
Теперь, когда ваш сервер Docker Registry запущен и принимает файлы большого размера, вы можете попробовать отправить на него образ. Поскольку у вас нет готовых образов, вы будете использовать образ
ubuntu
из Docker Hub, общедоступного реестра Docker, чтобы проверить это.В новом сеансе терминала для вашего клиентского сервера выполните следующую команду, чтобы загрузить образ
ubuntu
, запустить его и получить доступ к его оболочке:- docker run -t -i ubuntu /bin/bash
Флаги
-i
и-t
дают вам интерактивный доступ оболочки к контейнеру.Как только вы войдете, создайте файл с именем
SUCCESS
, запустив:- touch /SUCCESS
Создав этот файл, вы настроили свой контейнер. Позже вы будете использовать его, чтобы убедиться, что вы используете точно такой же контейнер.
Выйдите из оболочки контейнера, выполнив:
- exit
Теперь создайте новый образ из контейнера, который вы только что настроили:
- docker commit $(docker ps -lq) test-image
Новый образ теперь доступен локально, и вы отправите его в реестр контейнеров. Во-первых, вы должны войти в систему:
- docker login https://your_domain
При появлении запроса введите имя пользователя и пароль, которые вы определили на шаге 3.
Вывод будет:
Output... Login SucceededПосле входа переименуйте созданный образ:
- docker tag test-image your_domain/test-image
Наконец, отправьте образ с новым тегом в свой реестр:
- docker push your_domain/test-image
Вы получите вывод, подобный следующему:
OutputUsing default tag: latest The push refers to a repository [your_domain/test-image] 1cf9c9034825: Pushed f4a670ac65b6: Pushed latest: digest: sha256:95112d0af51e5470d74ead77932954baca3053e04d201ac4639bdf46d5cd515b size: 736Вы убедились, что ваш реестр обрабатывает аутентификацию пользователей путем входа в систему и что он позволяет пользователям, прошедшим проверку подлинности, отправлять изображения в реестр. Теперь вы попытаетесь извлечь образ из реестра.
Шаг 7 — Извлечение из вашего частного реестра Docker
Теперь, когда вы отправили образ в свой частный реестр, вы попытаетесь извлечь из него данные.
На главном сервере войдите в систему с именем пользователя и паролем, которые вы установили ранее:
- docker login https://your_domain
Попробуйте получить
test-image
, запустив:- docker pull your_domain/test-image
Docker загрузит образ. Запустите контейнер с помощью следующей команды:
- docker run -it your_domain/test-image /bin/bash
Он загрузит оболочку для контейнера.
Перечислите имеющиеся файлы, запустив:
- ls
Список файлов будет включать файл
SUCCESS
, который вы создали ранее, подтверждая, что этот контейнер использует тот же образ, который вы создали:- SUCCESS bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
Выйдите из оболочки контейнера:
- exit
Вы протестировали отправку и получение изображений и завершили настройку безопасного реестра, который можно использовать для хранения пользовательских образов.
Заключение
В этом руководстве вы настроили собственный частный реестр Docker и опубликовали в нем образ Docker. Как упоминалось во введении, вы также можете использовать TravisCI или аналогичный инструмент CI для автоматизации прямой отправки в частный реестр.
Используя контейнеры Docker в своем рабочем процессе, вы можете быть уверены, что образ, содержащий код, будет вести себя одинаково на любой машине, будь то рабочая или разрабатываемая. Для получения дополнительной информации о написании файлов Docker вы можете посетить официальную документацию по лучшим практикам.
- Зарегистрированное доменное имя, которое разрешается в сервер, который вы используете для размещения частного реестра Docker. Вы настроите это как часть предварительного условия Let’s Encrypt. В этом руководстве мы будем называть его