Docker одна из горячих тем в разработке. Большинство новых проектов строится именно на Docker. Как минимум, он отлично зарекомендовал себя для распространения ПО, например, наша система поиска по документам Ambar устанавливается с помощью docker-compose
.
В начале работы над Ambar мы использовали публичный docker-репозиторий, но с ростом проекта и появлением enterprise версии мы задумались над созданием собственного приватного репозитория. В данной статье мы поделимся своим опытом развертывания селф-хостед репозитория: пошагово опишем весь процесс, попытаемся обойти все подводные камни.
Локальный docker-репозиторий
Итак, простейший Docker-репозиторий можно поднять одной командой
docker run -d -p 5000:5000 --restart=always --name registry registry:2
Для проверки репозитория зальем в него образ ubuntu.
- Сначала скачаем образ с официального репозитория и добавим ему тег
localhost:5000/ubuntu
. - Запушим образ в наш новый репозиторий:
docker push localhost:5000/ubuntu
.
Хорошо, теперь мы умеем работать с локальным docker-репозиторием. Чтобы каждый раз не вспоминать команду запуска репозитория давайте создадим docker-compose.yml
файл:
registry:
restart: always
image: registry:2
ports:
- 5000:5000
volumes:
- /path/data:/var/lib/registry /* раздел который будет использоваться как хранилище для вашего репозитория*/
Чтобы запустить репозиторий достаточно ввести команду docker-compose up -d
в директории с docker-compose
файлом. С локальным репозиторием разобрались, перейдем к настройке SSL.
Настройка SSL
Зачем нужен SSL? Docker-репозиторий который доступен из интернета должен работать только через защищенное https соединение. Есть возможность обойти это ограничение, использовать самоподписанные сертификаты, но как показывает практика это работает через раз и легче один раз настроить все правильно, благо для тех у кого нет SSL сертификата я расскажу как использовать Letsencrypt. Стоит упомянуть что SSL является обязательным условием для работы аутентификации в репозитории.
Если у вас есть SSL сертификат — указываем путь к нему в docker-compose файле, смотрите листинг ниже.
registry:
restart: always
image: registry:2
ports:
- 5000:5000
environment:
REGISTRY_HTTP_TLS_CERTIFICATE: /certs/domain.crt
REGISTRY_HTTP_TLS_KEY: /certs/domain.key
volumes:
- /path/data:/var/lib/registry
- /path/certs:/certs /* папка где хранитcя сертификат */
Если же SSL сертификата нет — лучший выход использовать Letsencrypt. В последних версиях docker он работает из коробки без предварительного создания сертификатов, правда рабочего примера я нигде не нашел, поэтому приведу его здесь.
registry:
restart: always
image: registry:2
ports:
- 443:5000 /* важно поменять порт с на 443, иначе letsencrypt работать не будет */
environment:
REGISTRY_HTTP_TLS_LETSENCRYPT_CACHEFILE: /cache.letsencrypt /* файл в котором будет храниться кэш letsencrypt*/
REGISTRY_HTTP_TLS_LETSENCRYPT_EMAIL: hello@rdseventeen.com /* email, который будет использоваться для создания учетной записи в letsencrypt */
volumes:
- /path/data:/var/lib/registry
Стоит обратить внимание на то что для корректной работы Letsencrypt необходимо поменять порт с 5000 на 443. Расположение кеша Letsencrypt может быть любым.
Для тестирования нашего репозитория выполним следующие команды:
docker pull ubuntu
docker tag ubuntu myregistrydomain.com:443/ubuntu
docker push myregistrydomain.com:443/ubuntu
docker pull myregistrydomain.com:443/ubuntu
Настраиваем аутентификацию
Защитим наш репозиторий паролем. Для этого необходимо создать файл с паролями и указать его docker-репозиторию. Следующая команда создаст пользователя testuser
с паролем testpassword
, поместит их в файл и сохранит его в path/auth/htpasswd.
docker run --entrypoint htpasswd registry:2 -Bbn testuser testpassword > path/auth/htpasswd
В docker-compose укажем путь к файлу с паролями и использование basic аутентификации
registry:
restart: always
image: registry:2
ports:
- 443:5000
environment:
REGISTRY_HTTP_TLS_LETSENCRYPT_CACHEFILE: /cache.letsencrypt
REGISTRY_HTTP_TLS_LETSENCRYPT_EMAIL: hello@rdseventeen.com
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
volumes:
- /path/data:/var/lib/registry
- /path/auth:/auth
Для того чтобы изменения вступили в силу необходимо перезапустить docker-репозиторий. Используем команду docker-compose restart
. Логинимся в созданный репозиторий с помощью команды docker login myregistrydomain.com:443
. После этого наш репозиторий будет доступен для скачивания хранящихся в нём образов.
Итог
В статье мы рассмотрели создание приватного docker-репозитория. Для глубокого изучения темы рекомендую ознакомиться с официальным мануалом и списком настроек репозитория.
Спасибо за внимание!
Комментарии (14)
grossws
01.02.2017 03:58+2Я уж надеялся на что-нибудь интересное (например, настройка OAuth2 для авторизации действий с образами), а тут меньше чем в минималистичной официальной документации.
Lelik13a
01.02.2017 06:28+2Перевод документации, а надеялся на интересное.
И по моему, удобнее будет перед репозиторием поставить nginx и SSL часть и авторизацию вынести на него.
AccessGranted
01.02.2017 07:55Поднимал тоже свой репозиторий для использования в проде но понял что нет необходимости. Для базовых образов хватает и официального а собранные образы вместе с кодом льются на боевые сервера как архивы дабы размеры (от 100 до 200Mb) позволяют это делать.
summerwind
04.02.2017 19:05Подскажите, какой командой вы удаляете старый образ из приватного репозитория, прежде чем залить новый?
D1abloRUS
06.02.2017 12:51А для чего его удалять? залейте по верх с тем же тегом к примеру. Если идет версирование и старый тэг не нужен, можете через api и curl запросы это дело наскрептить. https://docs.docker.com/registry/spec/api/
summerwind
06.02.2017 14:45А вы сами хоть пробовали удалять образы через это api?) Какие бы запросы на удаление я не посылал — удаляется только метаинформация, но физически занятое место не освобождается. Пробовал чистить сборщиком мусора после выполнения запросов — тоже 0 эффекта.
P. S. Ну очевидно же, что не хочется хранить кучу образов старых версий) Если сборки идут каждый день + приложение не одно, а их несколько + образы весят под 2 Гб — посчитайте, насколько быстро забьется даже терабайтный хард.D1abloRUS
06.02.2017 16:03https://github.com/andrey-pohilko/registry-cli
summerwind
06.02.2017 17:16Это же просто обертка над api. Что принципиально нового она дает?
D1abloRUS
06.02.2017 17:31https://github.com/andrey-pohilko/registry-cli/blob/master/registry.py, открываем исходиник, читаем, как сделать чтобы место на hdd очищалось, после удаления тегов. и вот это еще заодно, чтобы удаление работало — https://github.com/andrey-pohilko/registry-cli#enable-image-deletion-in-docker-registry
summerwind
06.02.2017 17:49Я, конечно, попробую еще раз, но я вроде писал выше, что я пробовал запускать сборщик мусора после выполнения запросов и место не очищалось (REGISTRY_STORAGE_DELETE_ENABLED, само собой, true).
Rzhepish
А какой-то cleaner для старых версий образов использовали?
sochix
Раньше у нас был Jenkins и в нем был скрипт который выполнялся каждый день и удалял старые образы. Сейчас мы перешли на Buddy Works — он умеет удалять старые образы за нас