TLS 背后的 Docker Registry 启用了反向代理 (Traefik) - 远程错误 : Bad Certificate

标签 docker ssl reverse-proxy docker-registry traefik

所以我在这里做所有 Dockerized 的事情。 Traefik 在容器中运行,就像我的 docker Registry 实例一样。如果我在 mydomain.com:5000/myimage 中点击它,我就可以从注册表中推送/拉取它。

当我尝试使用 mydomain.com/myimage 通过 443 访问它时,问题就来了。我这里的设置是 Traefik 反向代理在 mydomain.com 上监听 443,并将该请求在内部转发到我的注册表实例的 :5000

当我从 Traefik url 推/拉时,它挂起并倒计时等待重试循环。当我查看 Registry 的日志时,我可以看到每个实例实际上都在与反向代理 Traefik 通信,但是,我在日志中一遍又一遍地收到此错误(在客户端的每次推送重试时):

2018/05/31 21:10:43 http:来自 proxy_container_ip 的 TLS 握手错误:端口:远程错误:tls:证书错误

Docker Registry 在 TLS 问题上非常严格。我在这里使用所有自签名证书,因为我仍在开发中。 知道是什么导致了这个错误吗?我假设 Traefik 代理检测到注册表提供的证书不受信任(自签名),因此没有完成“推送” "请求,或者相反 - 注册表,当将响应发送回 Traefik 代理时检测到它是不可信的。

如果需要,我可以提供更多信息。当前的设置是 Traefik 和 Registry 都有自己的一组 .crt 和 .key 文件。两者(当然)都启用了 TLS。

谢谢。

最佳答案

这是一个带有自签名证书的有效解决方案,您可以在 https://labs.play-with-docker.com 上试用

服务器

添加新实例 node1在你的 Docker Playground 上。我们将其配置为我们的服务器。为证书创建一个目录:

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 []:

在目录/root 中创建两个文件docker-compose.ymltraefik.toml .您可以使用以下方式下载它们:

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 root@registry.domain.local:/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"
  ]
}

关于TLS 背后的 Docker Registry 启用了反向代理 (Traefik) - 远程错误 : Bad Certificate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50633320/

相关文章:

python - 使用python脚本启动docker容器

azure - 在 azure devops : how can I inject my pipeline variables as appsettings when deploying a docker container to azure?

apache - .htaccess 非 www 重定向到根文件夹的子文件夹

node.js - Node + Docker撰写: Development and production setup

docker - cadvisor和influxDB集成问题

c++ - boost asio SSL双向身份验证

go - 需要帮助在 Go 中自动化 TLS 证书处理

azure - 使用 Azure 平台的 ARR 反向代理

java - nginx - Spring Boot 应用程序的多个反向代理(启用 Spring Security)

java - Apache Camel 作为反向代理