Docker容器虚拟主机SSL配置

Jay*_*ard 4 apache ssl virtualhost http-proxy docker

我有以下设置并且工作正常(我在 Docker 1.6 上):

在此处输入图片说明

一个 Docker 容器充当在各个 Docker 容器中运行的其他 Web 应用程序的虚拟主机代理。(我应该补充一点,我不是配置服务器或网络方面的高手。)

我一直在尝试将 SSL 添加到设置中,但收效甚微。每个容器在主机上挂载证书的文件目录。例如,一旦我使用以下命令运行容器:

docker run -d -P --name build \
    -v /home/applications/src/ssl-cert:/etc/ssl/certs \
    -e "DBL=mysql:dbname=build;host=192.168.0.1;port=3306" \
    -e "DB_USER=foo" -e "DB_PASS=bar" \
    --link mysql56:mysql \
    --add-host dockerhost:`/sbin/ip addr | grep 'eth0' | grep 'inet' | cut -d'/' -f1 | awk '{print $2}'` \
    -p 8001:80 -p 4431:443 \
     repos/build:latest
Run Code Online (Sandbox Code Playgroud)

如果我尝试连接,https://build.example.com我会收到证书错误并且无法连接。容器的 Apache 配置在证书文件的 default-ssl.conf 中有适当的配置(如果这是一个独立的实例,它可以工作):

<VirtualHost _default_:443>
    ServerAdmin webmaster@localhost

    DocumentRoot /var/www/html/

    # Enable/Disable SSL for this virtual host.
    SSLEngine on

    SSLProtocol all -SSLv2 -SSLv3
    SSLHonorCipherOrder On
    SSLCipherSuite ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS

    SSLCertificateFile /etc/ssl/certs/build.crt
    SSLCertificateKeyFile /etc/ssl/certs/build.key
    SSLCACertificateFile /etc/ssl/certs/digicert/digicertca.crt

    #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
    <FilesMatch "\.(cgi|shtml|phtml|php)$">
        SSLOptions +StdEnvVars
    </FilesMatch>
    <Directory /usr/lib/cgi-bin>
        SSLOptions +StdEnvVars
    </Directory>

    BrowserMatch "MSIE [2-6]" \
        nokeepalive ssl-unclean-shutdown \
        downgrade-1.0 force-response-1.0
    # MSIE 7 and newer should be able to use keepalive
    BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown

</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

然后我尝试为代理容器运行以下命令:

docker run -it -d -P --name apache_proxy \
    -v /home/applications/src/ssl-cert:/etc/ssl/certs \
    -p 8000:80 -p 443:443 \
    repos/apache-proxy:latest
Run Code Online (Sandbox Code Playgroud)

此容器还包含相同的 default-ssl.conf。

我尝试在几种不同的配置中运行它:

  • 仅在 Apache 代理容器中运行 SSL 配置
  • 仅在构建应用程序容器中运行 SSL 配置
  • 在两个容器中运行 SSL 配置

如果感觉好像我遗漏了一些明显的东西,但无法确定它会是什么。在这样的配置中运行 SSL 时,我是否遗漏了什么?

Cy *_*nol 7

当我们想为反向代理后面的主机添加 SSL 时,我们可以通过三种方式配置主机:

  • 边缘:反向代理解密传入的 HTTPS 流量并通过纯文本 HTTP 与后端服务器通信。
  • 直通:后端服务器解密所有流量,反向代理只是将 HTTPS 请求转发给它们。
  • 混合:反向代理解密 HTTPS 流量,然后重新加密绑定到后端服务器的流量。

第一个选项最容易设置——我们只需要在反向代理上安装证书和配置 SSL。第二种“直通”方法使后端服务器能够独立管理它们的 SSL 配置,但反向代理现在是“盲”的,因为它无法读取加密流量,我们可能希望这样做(例如)日志记录。当代理必须读取流量但我们也不信任代理和后端服务器之间的网络时,我们将使用第三种混合配置。

根据问题中的信息,第一个选项似乎最合适,因为我们信任反向代理和后端服务器之间的内部 Docker 网络。我们可以从后端服务器中删除 SSL 配置,并将来自反向代理的请求转发到它们的标准 HTTP 端口。

此设置需要两个附加组件:

  • 在代理上配置的基于名称的虚拟主机为每个后端服务转发请求。
  • 保护所有后端域名的单个证书(作为多个主题或作为通配符,如*.example.com)。

这是我们可以构建的示例虚拟主机配置部分:

<VirtualHost *:443>
    ServerName build.example.com
    ProxyRequests Off
    ProxyPreserveHost On 
    ProxyPass / http://build:8001/ 
    ProxyPassReverse / http://build:8001/
</VirtualHost>
<VirtualHost *:443>
    ServerName cicd.example.com
    ProxyRequests Off
    ProxyPreserveHost On 
    ProxyPass / http://cicd:8002/ 
    ProxyPassReverse / http://cicd:8002/
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

...并记住在默认虚拟主机块中配置 SSL 指令。如果我们链接容器或在同一个 Docker 网络上运行它们,我们可以在httpd.conf 中使用它们的容器名称作为主机名,如上所示。


说到网络,这个问题似乎表明我们需要仔细研究Docker 网络,因为我没有看到任何表明容器被配置为相互通信的提示(503 响应状态支持这个假设)。反向代理容器必须将请求转发到每个后端容器,但除非我们链接容器已弃用)或在容器之间创建内部用户定义网络,否则它无法这样做:

$ docker network create build_network
$ docker run --network build_network --name apache_proxy ...
$ docker run --network build_network --name build ...
$ docker run --network build_network --name cicd ...
Run Code Online (Sandbox Code Playgroud)

当我们在同一个用户定义的网络上运行容器时,它们可以通过 Docker 的内部 DNS 解析器通过容器名称解析其他容器的 IP 地址(如果我们将--hostname参数指定为 ,则通过备用主机名docker run)。还要注意,因为每个容器代表离散主机,所以我们不需要增加它们的端口号(80018002等)。我们可以使用端口 80 为来自内部网络上每个容器的 HTTP 流量提供服务。

$ docker network create build_network
$ docker run --network build_network --name apache_proxy ...
$ docker run --network build_network --name build ...
$ docker run --network build_network --name cicd ...
Run Code Online (Sandbox Code Playgroud)

  • @Jay 抱歉——我把“1.6”误读为“1.16”……有一段时间没看到 1.6 的盒子了!可能是升级的时候了 :) 很高兴这成功了! (2认同)