Реестр Docker за обратным прокси-сервером с поддержкой TLS (Traefik) - удаленная ошибка: недопустимый сертификат

Итак, я делаю здесь все, что Dockerized. Traefik работает в контейнере, как и мой экземпляр Docker Registry. Я могу просто нажать / вытащить из реестра, если нажму на mydomain.com:5000/myimage.

Проблема возникает, когда я пытаюсь пройти через 443, используя mydomain.com/myimage. У меня есть настройка обратного прокси Traefik, который прослушивает 443 в mydomain.com и перенаправляет этот запрос внутри :5000 моего экземпляра реестра.

Когда я перехожу на push / pull с URL-адреса Traefik, он зависает и ведет обратный отсчет, ожидая повторной попытки в цикле. Когда я смотрю журналы реестра, я вижу, что каждый экземпляр IS на самом деле взаимодействует с обратным прокси-сервером Traefik, однако я получаю эту ошибку в журнале снова и снова (при каждом повторном нажатии со стороны клиента):

2018/05/31 21:10:43 http: TLS handshake error from proxy_container_ip:port: remote error: tls: bad certificate

Реестр Docker очень жесткий и строгий, когда речь идет о проблеме TLS. Здесь я использую все самоподписанные сертификаты, так как я все еще в разработке. Есть идеи, что вызывает эту ошибку? Я предполагаю, что прокси Traefik обнаруживает, что сертификат, предложенный из реестра, не является доверенным (самоподписанный), и поэтому не выполняет "push "запрос, или наоборот - реестр при отправке ответа обратно на прокси-сервер Traefik обнаруживает, что ему нельзя доверять.

При необходимости могу предоставить дополнительную информацию. Текущая настройка такова, что и Traefik, и Registry имеют собственный набор файлов .crt и .key. Оба (конечно) TLS включены.

Спасибо.


person TyRyDurden    schedule 31.05.2018    source источник
comment
Какую установку вы используете? Работает ли эта установка Docker Swarm stackoverflow.com/a/51381036/1065654, если вы используете свой самоподписанный сертификат?   -  person maiermic    schedule 17.07.2018


Ответы (1)


Вот рабочее решение с самозаверяющим сертификатом, которое вы можете попробовать на https://labs.play-with-docker.com

Сервер

Добавьте новый экземпляр node1 на свою площадку Docker. Настраиваем его как наш сервер. Создайте каталог для сертификатов:

mkdir /root/certs

Создать подстановочный сертификат *.domain.local:

$ openssl req -newkey rsa:2048 -nodes -keyout /root/certs/domain.local.key -x509 -days 365 -out /root/certs/domain.local.crt
Generating a 2048 bit RSA private key
...........+++
...........+++
writing new private key to '/root/certs/domain.local.key'
-----
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) []:
State or Province Name (full name) []:
Locality Name (eg, city) []:
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:*.domain.local
Email Address []:

Создайте два файла docker-compose.yml и traefik.toml в каталоге /root. Вы можете скачать их, используя:

wget https://gist.github.com/maiermic/cc9c9aab939f7ea791cff3d974725e4a/raw/8c5d787998d33c752f2ab369a9393905780d551c/docker-compose.yml
wget https://gist.github.com/maiermic/cc9c9aab939f7ea791cff3d974725e4a/raw/8c5d787998d33c752f2ab369a9393905780d551c/traefik.toml

docker-compose.yml

version: '3'

services:
  frontproxy:
    image: traefik
    command: --api --docker --docker.swarmmode
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./certs:/etc/ssl:ro
      - ./traefik.toml:/etc/traefik/traefik.toml:ro
      - /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events
    deploy:
      labels:
        - traefik.port=8080
        - traefik.frontend.rule=Host:traefik.domain.local
  docker-registry:
    image: registry:2
    deploy:
      labels:
        - traefik.port=5000 # default port exposed by the registry
        - traefik.frontend.rule=Host:registry.domain.local
        - traefik.frontend.auth.basic=user:$$apr1$$9Cv/OMGj$$ZomWQzuQbL.3TRCS81A1g/ # user:password, see https://docs.traefik.io/configuration/backends/docker/#on-containers

traefik.toml

defaultEntryPoints = ["http", "https"]

# Redirect HTTP to HTTPS and use certificate, see https://docs.traefik.io/configuration/entrypoints/
[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      certFile = "/etc/ssl/domain.local.crt"
      keyFile = "/etc/ssl/domain.local.key"

# Docker Swarm Mode Provider, see https://docs.traefik.io/configuration/backends/docker/#docker-swarm-mode
[docker]
endpoint = "tcp://127.0.0.1:2375"
domain = "docker.localhost"
watch = true
swarmMode = true

Инициализируйте Docker Swarm (замените <ip-of-node1> IP-адресом node1, например 192.168.0.13):

docker swarm init --advertise-addr <ip-of-node1>

Разверните реестр traefik и Docker:

docker stack deploy myregistry -c ~/docker-compose.yml

Клиент

Поскольку у нас нет DNS-сервера, мы меняем /etc/hosts (заменяем <ip-of-node1> IP-адресом нашего сервера node1, например 192.168.0.13):

echo "<ip-of-node1>   registry.domain.local traefik.domain.local" >> /etc/hosts

Теперь у вас должна быть возможность запрашивать состояние здоровья у traefik.

$ curl -ksS https://traefik.domain.local/health | jq .
{
  "pid": 1,
  "uptime": "1m37.501499911s",
  "uptime_sec": 97.501499911,
  "time": "2018-07-19 07:30:35.137546789 +0000 UTC m=+97.600568916",
  "unixtime": 1531985435,
  "status_code_count": {},
  "total_status_code_count": {},
  "count": 0,
  "total_count": 0,
  "total_response_time": "0s",
  "total_response_time_sec": 0,
  "average_response_time": "0s",
  "average_response_time_sec": 0
}

и у вас должна быть возможность запрашивать все изображения (ни одного) из нашего реестра.

$ curl -ksS -u user:password https://registry.domain.local/v2/_catalog | jq .
{
  "repositories": []
}

Настроим docker на нашем клиенте. Создайте каталог для сертификатов реестра:

mkdir -p /etc/docker/certs.d/registry.domain.local/

Получите сертификат с нашего сервера:

scp [email protected]:/root/certs/domain.local.crt /etc/docker/certs.d/registry.domain.local/ca.crt # Are you sure you want to continue connecting (yes/no)? yes

Теперь вы можете войти в наш реестр и добавить изображение:

docker login -u user -p password https://registry.domain.local
docker pull hello-world:latest
docker tag hello-world:latest registry.domain.local/hello-world:latest
docker push registry.domain.local/hello-world:latest

Если после этого вы запросите все изображения из нашего реестра, вы должны увидеть

$ curl -ksS -u user:password https://registry.domain.local/v2/_catalog | jq .
{
  "repositories": [
    "hello-world"
  ]
}
person maiermic    schedule 19.07.2018
comment
@TyRyDurden Я протестировал полную процедуру @maiermic на labs.play-with-docker.com (фантастика!) с отличными результатами (спасибо !!!) Вероятно, ваша ошибка с сертификатом связана с тем, что на этапе копирования сертификата в /etc/docker/certs.d/YOUR_DOMAIN/ca.crt. Обратите внимание, что он должен называться ca.crt в папке вашего домена в /etc/docker/certs.d на клиентском хосте, откуда вы хотите получить доступ к реестру. - person pperejon; 12.02.2019