nginx重定向到docker容器

问题描述 投票:5回答:4

在发布我的问题之前,我想知道是否有可能实现我想要的。

我有,比方说,运行带有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 docker url-redirection
4个回答
5
投票

据我所知,你的nginx反向代理与容器在同一网络上,所以不需要用TLS保护它们之间的连接(因为这是一个专用网络,如果攻击者可以访问该网络,他会有访问服务器,以及所有未加密的数据)。

如果您绝对需要有效的证书来保护本地网络上的连接,则可以创建其他子域,这些子域可以解析为本地IP。然后,您将需要使用手动DNS选项来获取证书(这是一个certbot选项,您需要手动输入密钥作为您域的TXT条目)。

示例Nginx配置将http重定向到https

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;
}

1
投票

我会选择开箱即用的解决方案:

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容器将请求证书(并执行续订)。

更多:Nginx+LetsEncrypt


1
投票

这是我的方法:

NGINX Config file (default.conf)

使用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

这是我的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'

Testing

对于本地测试,通过将myhost.com添加到127.0.0.1来更改文件/ etc / hosts并运行以下命令:

卷曲 - 我http://www.myhost.com/

Result

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

0
投票

好的,我最终可以通过合并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文件中的错误导致容器无法启动,它将使生活更容易。

非常感谢大家的投入,现在拼图完成;-)

© www.soinside.com 2019 - 2024. All rights reserved.