nginx重定向到docker容器

时间:2016-12-21 14:41:10

标签: nginx docker url-redirection

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

我可以说,myserver.com使用nginx&运行一个docker容器。 letsencrypt。在同一台服务器上还有两个运行网站的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

4 个答案:

答案 0 :(得分:5)

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

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

将http重定向到https

的示例Nginx配置
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 :(得分: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

答案 2 :(得分:1)

这是我的方法:

NGINX配置文件(default.conf)

使用https://github.com/KyleAMathews/docker-nginx中的泊坞窗图像,我按如下方式执行了自定义默认文件:

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'

测试

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

curl -I 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

答案 3 :(得分: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

然后使用网络服务器运行任何容器;无需设置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文件中的错误导致容器无法启动,它将使生活更容易。

非常感谢大家的投入,现在这个难题已经完成; - )