首页 文章

nginx重定向到docker容器

提问于
浏览
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

4 回答

  • 1

    据我所知,你的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

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

    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

  • 5

    这是我的方法:

    NGINX配置文件(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'
    

    测试

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

    卷曲-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
    
  • 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文件中的错误导致容器无法启动,它将使生活更容易 .

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

相关问题