在发布我的问题之前,我想知道是否有可能实现我想要的。
我有,比方说,运行带有nginx和letsencrypt的docker容器的myserver.com。在同一台服务器上还有2个运行网站的docker容器。
现在所有的都被重定向好了,所以www.myserver.com去了docker 1而site2.myserver.com去了docker 2。
我希望通过HTTPS运行所有通信,但这里开始麻烦。所以,我的问题是:使用来自letsencrypt的证书,使用nginx和letsencrypt的docker是否可以连接到另一个docker?对我来说,它似乎是某种中间人“攻击”。更多原理图:
浏览到http:// site2.myserver.com - > nginx重定向到https:// site2.myserver.com - >连接到端口80上的容器2(192.168.0.10)。或者另一个选项:浏览到http:// site2.myserver.com - > nginx重定向到https:// site2.myserver.com - >连接到具有site2.myserver.com证书的端口443上的容器2(192.168.0.10)。
如果无法完成,那么解决方案是什么?将证书复制到docker容器并使它们运行https,以便将http请求重定向到该容器的https端口?
浏览到http:// site2.myserver.com - > nginx转发请求 - >连接到具有site2.myserver.com证书的端口443上的容器2(192.168.0.10)。
谢谢,Greggy
据我所知,你的nginx反向代理与容器在同一网络上,所以不需要用TLS保护它们之间的连接(因为这是一个专用网络,如果攻击者可以访问该网络,他会有访问服务器,以及所有未加密的数据)。
如果您绝对需要有效的证书来保护本地网络上的连接,则可以创建其他子域,这些子域可以解析为本地IP。然后,您将需要使用手动DNS选项来获取证书(这是一个certbot选项,您需要手动输入密钥作为您域的TXT条目)。
server {
listen 80;
server_name example.com;
return 301 https://example.com/;
}
server{
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
location / {
proxy_pass http://container:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
include tls.conf;
}
我会选择开箱即用的解决方案:
JWilder Nginx +让我们加密。
首先,我们启动NGINX Container作为反向代理:
docker run -d -p 80:80 -p 443:443 \
--name nginx-proxy \
-v /path/to/certs:/etc/nginx/certs:ro \
-v /etc/nginx/vhost.d \
-v /usr/share/nginx/html \
-v /var/run/docker.sock:/tmp/docker.sock:ro \
jwilder/nginx-proxy
接下来我们启动Lets Encrypt Container:
docker run -d \
-v /path/to/certs:/etc/nginx/certs:rw \
--volumes-from nginx-proxy \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
jrcs/letsencrypt-nginx-proxy-companion
对于您的网站,您需要设置一些环境变量:
docker run -d \
--name website1 \
-e "VIRTUAL_HOST=website1.com" \
-e "LETSENCRYPT_HOST=website1.com" \
-e "LETSENCRYPT_EMAIL=webmaster@website1" \
tutum/apache-php
Nginx容器将在其配置中创建一个新条目,并且let encrypt容器将请求证书(并执行续订)。
这是我的方法:
使用https://github.com/KyleAMathews/docker-nginx中的docker镜像,我按照以下方式执行了自定义默认文件:
server {
root /var/www;
index index.html index.htm;
server_name localhost MYHOST.COM;
# Add 1 week expires header for static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 1w;
}
location / {
# First attempt to serve request as file, then
# as directory, then fall back to redirecting to index.html
try_files $uri $uri/ @root;
return 301 https://$host$request_uri;
}
# If nginx can't find a file, fallback to the homepage.
location @root {
rewrite .* / redirect;
}
include /etc/nginx/basic.conf;
}
这是我的Dockerfile,考虑到我的静态内容在html /目录下。
COPY conf/default.conf /etc/nginx/sites-enabled/default
ADD certs/myhost.com.crt /etc/nginx/ssl/server.crt
ADD certs/myhost.com.key /etc/nginx/ssl/server.key
RUN ln -s /etc/nginx/sites-available/default-ssl /etc/nginx/sites-enabled/default-ssl
COPY html/ /var/www
CMD 'nginx'
对于本地测试,通过将myhost.com添加到127.0.0.1来更改文件/ etc / hosts并运行以下命令:
卷曲 - 我http://www.myhost.com/
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Sun, 04 Mar 2018 04:32:04 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://www.myhost.com/
X-UA-Compatible: IE=Edge
好的,我最终可以通过合并opHASnoNAME和Paul Trehiou的答案得到我想要的东西。我为opHASnoNAME的答案做的额外工作是在nginx和letsencrypt docker之间安装一个文件系统。它可以将nginx的配置文件链接到正确的证书(参见后面的内容)。
这就是我做的:
docker run --name nginx-prod --restart always -d -p 80:80 -p 443:443 -v /choose/your/dir/letsencrypt:/etc/nginx/certs:ro -v /etc/nginx/vhost.d -v /usr/share/nginx/html -v /var/run/docker.sock:/tmp/docker.sock:ro -e DEFAULT_HOST=myserver.com jwilder/nginx-proxy
docker run --name letsencrypt --restart always -d -v /choose/your/dir/letsencrypt:/etc/nginx/certs:rw --volumes-from nginx-prod -v /var/run/docker.sock:/var/run/docker.sock:ro jrcs/letsencrypt-nginx-proxy-companion
然后使用webserver运行任何容器;无需设置LETSENCRYPT变量。我可以在不设置的情况下访问我当前的容器。
jwilder / nginx-proxy将列出/etc/nginx/conf.d/default.conf中所有正在运行的容器。不要在此文件中添加任何内容,因为它会在下次重新启动时被覆盖。为每个Web服务器创建同一目录中的新.conf文件。此文件将包含Paul Trehiou建议的https信息。我创建了例如site2.conf:
server{
listen 443 ssl http2;
server_name site2.myserver.com;
ssl_certificate /etc/nginx/certs/live/myserver.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/live/myserver.com/privkey.pem;
ssl_trusted_certificate /etc/nginx/certs/live/myserver.com/fullchain.pem;
location / {
proxy_pass http://192.168.0.10/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
您可以从default.conf文件中获取proxy_pass地址,每个容器都列出了IP地址。为了能够备份这些.conf文件,我将重新创建我的nginx容器并将本地文件系统挂载到/etc/nginx/conf.d。如果由于.conf文件中的错误导致容器无法启动,它将使生活更容易。
非常感谢大家的投入,现在拼图完成;-)