DevOps, Linux, 2 git`a
  • Обо мне
  • Категории
  • Теги
  • Архив

Часть 2.1. Private registry. Авторизация. SSL. Web UI.

Содержание

  • Docker Hub vs. Private registry
  • Своё собственное хранилище
  • Сертификаты
  • Nginx
  • Авторизация и SSL
  • Web-ui registry interface
  • Запуск
  • Docker login, push
  • Поиск и веб интерфейс

Docker

Docker Hub vs. Private registry

Докер это не только набор программного обеспечения, но и инфраструктура в виде docker hub, где любой желающий может хранить образы в публичном доступе абсолютно бесплатно. Плюс этот хаб используется компаниями для выкладывания своих публичных образов ПО и операционных систем. Репозитории таких компаний проверены и безопасны (я надеюсь). Это очень удобно для опенсорс разработки, экспериментов и домашних проектов.
Docker как и github монетизирует свой сервис платными аккаунтами с частными(приватными) репозиториями. Но основание для создание своего частного хранилища образов даже не платность сервиса, а то что объемные образы внутрь своей инфраструктуры придется тянуть из интернета и при чем на каждый железный сервер по отдельности.

Своё собственное хранилище

Докер сам предоставляет образ с приватным хранилищем. Им я и воспользуюсь:

    docker pull registry

Эту команду я выполню на удаленном рабочем сервере. После скачивания образ можно будет увидеть в системе командой docker images

    REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
    registry            latest              fc251f2434a1        7 days ago          413.6 MB

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

Для создания такого контейнера потребуется следующий Dockerfile:

    FROM busybox

    VOLUME /registry/storage
    CMD /bin/sh

Это простейший контейнер на базе busybox в котором создан один том /registry/storage. Создадим контейнер на нашем сервере, выполнив команду рядом с нашим докерфайлом: docker build -t registry_datastore .

Для начала запустим хранилище в режиме без авторизации и поддержки ssl:

  • Проинициализируем контейнер с данными

    docker run --name registry_datastore registry_datastore true
    
  • Непосредственно запустим registry

    docker run --name registry --volumes-from registry_datastore \
    -e STORAGE_PATH=/registry/storage -e SEARCH_BACKEND=sqlalchemy \
    -p 10.200.200.28:5000:5000 -d registry
    

Контейнер с именем registry использует том /registry/storage от контейнера registry_datastore. Переменная STORAGE_PATH указывает путь до места хранения базы образов, а SEARCH_BACKEND включает встроенный в образ механизм поиска. Команда -p 10.200.200.28:5000:5000 пробрасывает на внутренний интерфейс сервера порт 5000, через который и будет осуществляться доступ к хранилищу.

Это минимальный запуск. Если вас не беспокоит авторизация и безопасность. И вы полностью доверяете своей локальной сети, то этого базового варианта хватит для использования в боевую.

Но если вам требуется авторизация и передача данных поверх HTTPS, то останавливаем и удаляем контейнер docker stop registry; docker rm registry и продолжаем.

Сертификаты

Инфраструктура будет построена по следующей схеме:

Docker
Бонусом будет добавлен web-ui интерфейс для обзора и поиска образов в хранилище.

Базовую авторизацию будет обеспечивать nginx, но по спецификации докера, если включена авторизация, то необходим протокол https. Значит понадобиться сделать самоподписанные сертификаты:

  • Создаю корневой ключ:

    openssl genrsa -out dev-docker-ca.key 2048
    
  • Генерирую корневой сертификат на основе ключа (можно вводить любые данные):

    openssl req -x509 -new -nodes -key dev-docker-ca.key -days 10000 -out dev-docker-ca.crt
    
  • Создам ключ для сайта registry:

    openssl genrsa -out dev-docker-registry.k12.key 2048
    
  • Далее необходимо создать запрос на сертификат для нашего сайта:

    openssl req -new -key dev-docker-registry.k12.key -out dev-docker-registry.k12.csr
    

Здесь будет диалог с мастером. В Common name необходимо указать имя вашего сайта для registry, в моём случае я имею внутреннюю зону .k12 и собственный dns, который эту зону обслуживает. И для Common name буду использовать registry.k12. На последнем этапе ввода пароля лучше оставить поля пустыми:

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:RU
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:K12
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:registry.k12
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
  • Далее следует создание сертификата сайта:

    openssl x509 -req -in dev-docker-registry.k12.csr -CA dev-docker-ca.crt -CAkey dev-docker-ca.key -CAcreateserial -out dev-docker-registry.k12.crt -days 10000
    
  • Так же, если вы планируете использовать веб-интерфейс, то необходимо подключить корневой сертификат к java внутри контейнера ui-registry, иначе этот шаг можно пропустить:

    keytool -importcert -file dev-docker-ca.crt -alias ca -keystore truststore -storepass PaSsw0Rd -noprompt
    

Утилита keytools входит в состав jdk. На основе корневого сертификата dev-docker-ca.crt создатся фaил truststore, который позднее будет подключен к java внутри контейнера с ui.

Nginx

Для создания контейнера nginx я использую Dockerfile из первой части статей, но необходимо внести модификации:

#
# Nginx stable Dockerfile
#

# Pull base image.
FROM phusion/baseimage

# Install Nginx.
RUN \
    add-apt-repository -y ppa:nginx/stable && \
    apt-get update && \
    apt-get install -y nginx apache2-utils && \
    echo "\ndaemon off;" >> /etc/nginx/nginx.conf && \
    chown -R www-data:www-data /var/lib/nginx && \
    unlink /etc/nginx/sites-enabled/default && \
    apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Runit Nginx service
ADD nginx.sh /etc/service/nginx/run

# Disable ipv6
ADD ipv6off.sh /etc/rc.local

# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]

Изменение одно, это установка пакета apache2-utils из которого будет использоваться утилита htpasswd.

Образ можно собрать: docker build -t nginx .

Авторизация и SSL

Для хранение конфигов nginx и сертификатов понадобится контейнер с данными. Его описание в следующем докерфайле:

    FROM busybox

    VOLUME /etc/nginx/conf.d
    VOLUME /etc/nginx/pki
    VOLUME /java-pki

    CMD /bin/sh

Создается три тома. Под конфиги nginx, сертификаты и ключи, и под хранилище ключей для java. Сборка образа и инициализация контейнера:

    docker build -t conf_datastore .
    docker run --name conf_datastore conf_datastore true

Будет использовано два сайта. Один непосредственно для private registry с адресом https://registry.k12, а так же веб интерфейс http://ui.registry.k12. За это будут отвечать следующие конфиги:

# registry.k12
upstream docker-registry {
 server registry:5000;
}

server {
listen 443;
server_name registry.k12;

ssl on;
ssl_certificate pki/dev-docker-registry.k12.crt;
ssl_certificate_key pki/dev-docker-registry.k12.key;

proxy_set_header Host       $http_host;   # required for Docker client sake
proxy_set_header X-Real-IP  $remote_addr; # pass on real client IP

 client_max_body_size 0;
 chunked_transfer_encoding on;

 location / {
        auth_basic              "Restricted";
        auth_basic_user_file    registry.htpasswd;
        proxy_pass http://docker-registry;
    }
location /_ping {
        auth_basic off;
        proxy_pass http://docker-registry;
    }
location /v1/_ping {
        auth_basic off;
        proxy_pass http://docker-registry;
    }
}

# ui.registry.k12
upstream docker-ui-registry {
 server ui-registry:8080;
}
server {
listen 80;
server_name ui.registry.k12;

proxy_set_header Host       $http_host;
proxy_set_header X-Real-IP  $remote_addr;

 location / {
        auth_basic              "Restricted";
        auth_basic_user_file    registry.htpasswd;
        proxy_pass http://docker-ui-registry;
    }
}

Данные конфиги, а так же сгенереннные файлы dev-docker-registry.k12.crt, dev-docker-registry.k12.key и truststore необходимо поместить в одну папку. Переходим внутрь этой папки и подключаемся к дата контейнеру conf_datastore следующей командой:

    docker run --rm -it --volumes-from conf_datastore -v `pwd`:/volume busybox  /bin/sh

Вы окажитесь внутри контейнера с доступом к томам conf_datastore и "прокинутой" внутрь контейнера папкой /volume. Теперь осталось разложить файлы по томам:

    root@server# docker run --rm -it --volumes-from conf_datastore -v `pwd`:/volume busybox  /bin/sh
    / # cd /volume
    /volume # ls -lA
    -rw-r--r--    1 root     root          1103 Mar 19 08:25 dev-docker-registry.k12.crt
    -rw-r--r--    1 root     root          1679 Mar 19 07:55 dev-docker-registry.k12.key
    -rw-r--r--    1 root     root           775 Mar 20 07:30 registry.k12.conf
    -rw-r--r--    1 root     root           910 Mar 20 08:59 truststore
    -rw-r--r--    1 root     root           374 Mar 20 07:31 ui.registry.k12.conf
    /volume # cp dev-docker-registry.k12.crt /etc/nginx/pki/
    /volume # cp dev-docker-registry.k12.key  /etc/nginx/pki/
    /volume # cp truststore /java-pki/
    /volume # cp *.conf /etc/nginx/conf.d/
    /volume # exit

Web-ui registry interface

Последний подготовительный этап - это веб интерфейс к хранилищу. Я для своих нужды выбрал docker-registry-ui.

    docker pull atcol/docker-registry-ui

Внутри контейнера находится java-tomcat сервер приложений и именно для него было необходимо создавать java хранилище сертификатов truststore.

Запуск

Теперь со всем этим необходимо взлететь в правильной последовательности.

Но перед запуском контейнеров необходимо на сервере зарегистрировать сгенерированный корневой сертификат.

    root@server# mkdir /usr/local/share/ca-certificates/dev-docker-ca
    root@server# cp dev-docker-ca.crt /usr/local/share/ca-certificates/dev-docker-ca/     # копирование корневого сертификата 
    root@server# update-ca-certificates
    Updating certificates in /etc/ssl/certs...
    1 added, 0 removed; done.
    Running hooks in /etc/ca-certificates/update.d....done.

Далее необходимо сделать рестарт главному демону докера: service docker restart

Корневой сертификат лучше положить в легкодоступное место, например по http, т.к. добавления сертификата в систему необходимо сделать на каждом железном сервере, который участвует в построении docker-инфраструктуры

Уже должны быть проинициализированы два контейнера с данными (registry_datastore, conf_datastore). Если нет, то необходимо сделать это:

    docker run --name registry_datastore registry_datastore true
    docker run --name conf_datastore conf_datastore true

Далее необходимо запустить контейнер registry:

    docker run --name registry --volumes-from registry_datastore \
    -e STORAGE_PATH=/registry/storage -e SEARCH_BACKEND=sqlalchemy -d registry

Следом контейнер с веб интерфейсом к хранилищу:

    docker run --name ui-registry --volumes-from conf_datastore \
    -e 'JAVA_OPTS=-Djavax.net.ssl.trustStore=/java-pki/truststore -Djavax.net.ssl.trustStorePassword=PaSsw0Rd' \
    -e REG1=https://registry.k12/v1/ \
    -d atcol/docker-registry-ui

Переменной 'JAVA_OPTS=-Djavax.net.ssl.trustStore=/java-pki/truststore -Djavax.net.ssl.trustStorePassword=PaSsw0Rd' java внутри контейнера ui-registry подхватит корнейвой сертификат из хранилища /java-pki/truststore под соответствующим паролем. Переменной REG1 задается адрес до api private registry.

В финале запускаю фронтенд - nginx:

    docker run --name nginx --link registry:registry --link ui-registry:ui-registry --volumes-from conf_datastore \
    -p 10.200.200.28:443:443 -p 10.200.200.28:80:80 -d nginx

Docker login, push

Подключусь к контейнеру nginx и создам фаил для базовой авторизации /etc/nginx/registry.htpasswd

    root@server# docker exec -it nginx /bin/bash
    root@d4b659658677:/# htpasswd -b /etc/nginx/pki/registry.htpasswd admin
    New password:
    Re-type new password:
    Adding password for user admin
    root@d4b659658677:/# exit

Теперь на сервере с докером можно логиниться:

    root@server# docker login registry.k12
    Username: admin
    Password:
    Email:
    Login Succeeded

Email можно оставить пустым.

Для того чтоб запушить образ в реджестри необходимо повесить правильный тег, а затем уже сделать пуш. Протестирую на образе nginx:

root@server# docker tag nginx registry.k12/nginx
root@server#
root@server# docker images | grep nginx
nginx                      latest              bbb605efa1e9        4 days ago          299.7 MB
registry.k12/nginx         latest              bbb605efa1e9        4 days ago          299.7 MB
root@server#
root@server# docker push registry.k12/nginx
The push refers to a repository [registry.k12/nginx] (len: 1)
Sending image list
Pushing repository registry.k12/nginx (1 tags)
511136ea3c5a: Image successfully pushed
53f858aaaf03: Image successfully pushed
837339b91538: Image successfully pushed
615c102e2290: Image successfully pushed
b39b81afc8ca: Image successfully pushed
8254ff58b098: Image successfully pushed
ec5f59360a64: Image successfully pushed
2ce4ac388730: Image successfully pushed
2eccda511755: Image successfully pushed
5a14c1498ff4: Image successfully pushed
83e12e068086: Image successfully pushed
c2db9a7375fb: Image successfully pushed
4cd8296c1a93: Image successfully pushed
bbb605efa1e9: Image successfully pushed
Pushing tag for rev [bbb605efa1e9] on {https://registry.k12/v1/repositories/nginx/tags/latest}

Поиск и веб интерфейс

Для того чтоб осуществить поиск в private registry можно воспользоваться api и curl`ом

# Вывод всех образов в хранилище
root@server# curl https://admin:SecRetPassWord@registry.k12/v1/search
{"num_results": 1, "query": "nginx", "results": [{"description": "", "name": "library/nginx"}]}

# Персонализированный поиск
root@server# curl https://admin:SecRetPassWord@registry.k12/v1/search?q=nginx
{"num_results": 1, "query": "nginx", "results": [{"description": "", "name": "library/nginx"}]}

# То же, но в человеческом виде
root@server# curl https://admin:SecRetPassWord@registry.k12/v1/search?q=nginx | python -mjson.tool
{
"num_results": 1,
"query": "",
"results": [
        {
            "description": "",
            "name": "library/nginx"
        }
        ]
}

Или можно использовать веб интерфейс. В моём случае нужно перейти на страницу http://ui.registry.k12

ui-docker

Необходимо заполнить Username и Password на странице добавления/редактирования хранилища.

ui-docker

Теперь возможно воспользоваться поиском.

ui-docker

На этом можно считать процесс внедрения private registry в инфраструктуру законченным. Веб интерфейс сделан для галочки и не несет особой нагрузки и юзабилити, но возможно будет улучшен в будущем и окажется более полезен. Приватное хранилище готово для централизованного распространения образов в частной сети. В следующей статье private registry будет использовано для запуска сервисов через docker. Одним из первых на очереди logstash.

Комментарии
comments powered by Disqus

Опубликовано

мар 24, 2015

Категория

devops

Теги

  • auth 2
  • ca 1
  • cert 1
  • data container 4
  • datastore 4
  • docker 4
  • java 1
  • nginx 5
  • registry 1
  • ssl 1

Контакты

Получать обновления

  • Creative Commons License DevOps, linux, 2 git`a. Дмитрий Леонов
  • Создано с помощью Pelican. Тема Elegant от Talha Mansoor. Перевод темы Дмитрий Леонов