Docker 容器虚拟主机 SSL 配置
Docker Container Virtual Host SSL Configuration
我有以下设置并且工作正常(我在 Docker 1.6):
一个 Docker 容器充当其他 Web 应用程序的虚拟主机代理 运行 在单独的 Docker 容器中。 (我应该补充一点,我不是配置服务器或网络的专家。)
我一直在尝试将 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 }'` \
-p 8001:80 -p 4431:443 \
repos/build:latest
如果我尝试连接到 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>
然后我尝试运行代理容器的以下内容:
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
此容器也包含相同的默认值-ssl.conf。
我已经尝试 运行在几种不同的配置中使用它:
- 运行仅在 Apache 代理容器中启用 SSL 配置
- 运行仅在构建应用程序容器中启用 SSL 配置
- 运行在两个容器中启用 SSL 配置
如果感觉好像我遗漏了一些明显的东西,但又无法确定它会是什么。在这样的配置中 运行ning SSL 时,我是否遗漏了什么?
通常情况下,如果您的服务器 运行 在 apache 服务器后面,您只需要将 Apache 配置为使用 SSL 证书。
如果 Apache 是唯一 "outside" 暴露的服务器,并且其他服务器无法从外界直接访问
你需要apache通过url或类似的端口代理到其他服务器,例如:
<VirtualHost *:443>
ServerName SERVERNAME_HERE
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
# Proxy pass to other server
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://OTHER_SERVER_IP_WITHIN_DOCKER_NETWORK:8081/
ProxyPassReverse / http://OTHER_SERVER_IP_WITHIN_DOCKER_NETWORK:8081/
<!--Other config-->
</VirtualHost>
希望对您有所帮助...
当我们想要将 SSL 添加到反向代理后面的主机时,我们可以通过三种方式配置主机:
- 边缘: 反向代理解密传入的 HTTPS 流量并通过纯文本 HTTP 与后端服务器通信。
- 直通: 后端服务器解密所有流量,反向代理只是将 HTTPS 请求转发给它们。
- 混合: 反向代理解密 HTTPS 流量,然后 重新加密 前往后端服务器的流量。
第一个选项最容易设置——我们只需要在反向代理上安装证书和配置 SSL。第二种 "pass-through" 方法使后端服务器能够独立管理其 SSL 配置,但反向代理现在是 "blind" 因为它无法读取加密流量,而我们可能希望为(示例)日志记录执行此操作.当代理必须读取流量但我们也不信任代理和后端服务器之间的网络时,我们会使用第三种混合配置。
根据问题中的信息,第一个选项似乎最合适,因为我们信任反向代理和后端服务器之间的内部 Docker 网络。我们可以从后端服务器中删除 SSL 配置,并将来自反向代理的请求转发到它们的标准 HTTP 端口。
此设置需要两个附加组件:
- 在代理上配置的基于名称的虚拟主机转发对 each 后端服务的请求。
- 一个单一证书,保护所有后端域名(作为多个主题或通配符,如 *.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>
...并记住在 default 虚拟主机块中配置 SSL 指令。如果我们 link 容器或 运行 它们在同一个 Docker 网络上,我们可以在我们的 httpd.conf[=64= 中使用它们的容器名称作为主机名] 如上所示。
说到网络,这个问题似乎表明我们需要仔细看看容器之间的Docker networking because I don't see any hints that indicate that the containers were configured to talk to each other (the 503 response status supports this assumption). The reverse proxy container must forward requests to each of the backend containers, but it cannot do so unless we link the containers (deprecated) or create an internal, user-defined network:
$ 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 ...
当我们 运行 容器在同一个用户定义的网络上时,它们可以通过 Docker 的内部 DNS 解析器(或备用主机名)按容器名称解析其他容器的 IP 地址如果我们将 --hostname
参数指定为 docker run
)。另请注意,因为每个容器代表离散的主机,所以我们不需要增加它们的端口号(8001、8002 等)。我们可以使用端口 80 为来自内部网络上每个容器的 HTTP 流量提供服务。
+────────────────── Docker Host ─────────────────+
│ +────────────── build_network ─────────────+ │
│ │ │ │
Client ────────────── apache_proxy (:443 → :443) │ │
│ │ ├── build (:80) │ │
│ │ └── cicd (:80) │ │
│ +──────────────────────────────────────────+ │
+────────────────────────────────────────────────+
我有以下设置并且工作正常(我在 Docker 1.6):
一个 Docker 容器充当其他 Web 应用程序的虚拟主机代理 运行 在单独的 Docker 容器中。 (我应该补充一点,我不是配置服务器或网络的专家。)
我一直在尝试将 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 }'` \
-p 8001:80 -p 4431:443 \
repos/build:latest
如果我尝试连接到 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>
然后我尝试运行代理容器的以下内容:
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
此容器也包含相同的默认值-ssl.conf。
我已经尝试 运行在几种不同的配置中使用它:
- 运行仅在 Apache 代理容器中启用 SSL 配置
- 运行仅在构建应用程序容器中启用 SSL 配置
- 运行在两个容器中启用 SSL 配置
如果感觉好像我遗漏了一些明显的东西,但又无法确定它会是什么。在这样的配置中 运行ning SSL 时,我是否遗漏了什么?
通常情况下,如果您的服务器 运行 在 apache 服务器后面,您只需要将 Apache 配置为使用 SSL 证书。 如果 Apache 是唯一 "outside" 暴露的服务器,并且其他服务器无法从外界直接访问
你需要apache通过url或类似的端口代理到其他服务器,例如:
<VirtualHost *:443>
ServerName SERVERNAME_HERE
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
# Proxy pass to other server
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://OTHER_SERVER_IP_WITHIN_DOCKER_NETWORK:8081/
ProxyPassReverse / http://OTHER_SERVER_IP_WITHIN_DOCKER_NETWORK:8081/
<!--Other config-->
</VirtualHost>
希望对您有所帮助...
当我们想要将 SSL 添加到反向代理后面的主机时,我们可以通过三种方式配置主机:
- 边缘: 反向代理解密传入的 HTTPS 流量并通过纯文本 HTTP 与后端服务器通信。
- 直通: 后端服务器解密所有流量,反向代理只是将 HTTPS 请求转发给它们。
- 混合: 反向代理解密 HTTPS 流量,然后 重新加密 前往后端服务器的流量。
第一个选项最容易设置——我们只需要在反向代理上安装证书和配置 SSL。第二种 "pass-through" 方法使后端服务器能够独立管理其 SSL 配置,但反向代理现在是 "blind" 因为它无法读取加密流量,而我们可能希望为(示例)日志记录执行此操作.当代理必须读取流量但我们也不信任代理和后端服务器之间的网络时,我们会使用第三种混合配置。
根据问题中的信息,第一个选项似乎最合适,因为我们信任反向代理和后端服务器之间的内部 Docker 网络。我们可以从后端服务器中删除 SSL 配置,并将来自反向代理的请求转发到它们的标准 HTTP 端口。
此设置需要两个附加组件:
- 在代理上配置的基于名称的虚拟主机转发对 each 后端服务的请求。
- 一个单一证书,保护所有后端域名(作为多个主题或通配符,如 *.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>
...并记住在 default 虚拟主机块中配置 SSL 指令。如果我们 link 容器或 运行 它们在同一个 Docker 网络上,我们可以在我们的 httpd.conf[=64= 中使用它们的容器名称作为主机名] 如上所示。
说到网络,这个问题似乎表明我们需要仔细看看容器之间的Docker networking because I don't see any hints that indicate that the containers were configured to talk to each other (the 503 response status supports this assumption). The reverse proxy container must forward requests to each of the backend containers, but it cannot do so unless we link the containers (deprecated) or create an internal, user-defined network:
$ 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 ...
当我们 运行 容器在同一个用户定义的网络上时,它们可以通过 Docker 的内部 DNS 解析器(或备用主机名)按容器名称解析其他容器的 IP 地址如果我们将 --hostname
参数指定为 docker run
)。另请注意,因为每个容器代表离散的主机,所以我们不需要增加它们的端口号(8001、8002 等)。我们可以使用端口 80 为来自内部网络上每个容器的 HTTP 流量提供服务。
+────────────────── Docker Host ─────────────────+
│ +────────────── build_network ─────────────+ │
│ │ │ │
Client ────────────── apache_proxy (:443 → :443) │ │
│ │ ├── build (:80) │ │
│ │ └── cicd (:80) │ │
│ +──────────────────────────────────────────+ │
+────────────────────────────────────────────────+