【问题标题】:Docker nginx proxy to hostDocker nginx 代理到主机
【发布时间】:2017-07-15 06:29:11
【问题描述】:

简短说明:

Nginx 在 docker 上运行,如何配置 nginx 以便将调用转发到主机。

详细说明:

我们有一个 Web 应用程序与几个后端通信(比如说 rest1、rest2 和 rest3)。我们负责rest1

假设我在我的电脑上手动启动了rest1 并在 2345 端口上运行。我希望 nginx(在 docker 中运行)将所有对rest1 的调用重定向到我自己正在运行的实例(注意,该实例在主机上运行,​​而不是在任何容器上运行,而不是在 docker 中)。对于 rest2rest3 到其他 docker 节点,或者可能是其他服务器(谁在乎)。

我正在寻找的是:

  1. docker-compose.yml 配置(如果需要)。
  2. nginx 配置。

提前致谢。

【问题讨论】:

    标签: nginx docker docker-compose


    【解决方案1】:

    如下配置nginx(确保替换Docker主机的IP)并保存为default.conf

    server {
        listen       80;
        server_name  _;
        location / {
            proxy_pass http://<IP of Docker Host>;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
    

    现在调出容器:

    docker run -d --name nginx -p 80:80 -v /path/to/nginx/config/default.conf:/etc/nginx/conf.d/default.conf nginx
    

    【讨论】:

    • 谢谢,还没有尝试,但我会尽快尝试。反正有没有自动化这个过程?我的意思是主机IP?因为我们想开发可以在每台机器上运行的东西。
    • 使用bash脚本,先hostname -I,然后grep范围,然后sed进入配置文件并替换。
    • 这些 IP 地址似乎都不起作用。我什至尝试过 0.0.0.0:5000 并得到 502 Bad Gateway。
    • @MarissaLevy 如果 docker-host 在容器可用的 DNS 服务器上有一个名称,您也可以使用 dns。
    • 如果 docker-for-mac 是主机,IP 是host.docker.internal - docs.docker.com/docker-for-mac/networking/…
    【解决方案2】:

    解决方案 1

    使用network_mode: host,这会将您的 nginx 实例绑定到主机的网络接口。 这可能会在运行多个 nginx 容器时导致冲突:每个暴露的端口都绑定到主机的接口。

    解决方案 2

    我正在为我想向外界公开的每项服务运行更多的 nginx 实例。 为了保持 nginx 配置简单并避免将每个 nginx 绑定到主机,请使用容器结构:

    dockerhost - 一个带有network_mode: host的虚拟容器

    proxy - nginx 容器用作托管服务的代理,

    dockerhost 链接到proxy,这将在proxy contianer 中添加一个/etc/hosts 条目 - 我们可以在 nginx 配置中使用 'dockerhost' 作为主机名。

    docker-compose.yaml

    version: '3'
    services:
      dockerhost:
        image: alpine
        entrypoint: /bin/sh -c "tail -f /dev/null"
        network_mode: host
      proxy:
        image: nginx:alpine
        links: 
         - dockerhost:dockerhost
        ports:
         - "18080:80"
        volumes:
         - /share/Container/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    

    default.conf

     location / {
            proxy_pass http://dockerhost:8080;
    

    这种方法使我们能够自动为我的服务器上运行的每个服务生成让我们加密的证书。如果有兴趣,我可以发布有关解决方案的要点。

    【讨论】:

    • 请分享要点
    • 其实我喜欢第二种解决方案,而且效果很好。谢谢。
    • 似乎解决方案 2 不再有效。代理容器的 /etc/hosts 中没有出现 dockerhost 记录
    【解决方案3】:

    如果您使用的是 Docker Compose 文件版本 3,则根本不需要对 docker-compose.yml 文件进行任何特殊配置,只需使用特殊 DNS 名称 host.docker.internal 即可访问主机服务,如下面的 nginx.conf示例:

    events {
        worker_connections  1024;
    }
    
    http {
        upstream host_service {
           server host.docker.internal:2345;
        }
    
        server {
            listen 80;
    
            access_log  /var/log/nginx/http_access.log  combined;
            error_log   /var/log/nginx/http_error.log;
    
            location / {
                proxy_pass http://host_service;
    
                proxy_set_header    Host                $http_host;
                proxy_set_header    X-Real-IP           $realip_remote_addr;
                proxy_set_header    X-Forwarded-Proto   $scheme;
                proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    
                proxy_http_version 1.1;
                proxy_set_header Connection "";
            }
        }
     }
    
    

    【讨论】:

    【解决方案4】:

    有几点需要注意:

    1. Docker compose(从版本 3 开始)默认使用服务名称作为容器间网络的主机名
    2. Nginx 需要先了解上游
    3. 我强烈建议将 default.conf 直接安装到您的 docker-compose.yml 中。
    4. 最后,您必须对后端进行 docker 化以使用 docker 内部网络。

    我在全栈项目中使用 nginx 和 docker-compose 的示例 repo:https://gitlab.com/datails/api

    以下示例有一些先决条件:

    • 您的文件夹结构如下:

      - backend/
      - frontend/
      - default.conf
      - docker-compose.yml
      
    • 其次,后端和前端的 dit 有一个 Dockerfile,它在端口 3000 上公开一个应用程序。

    例如default.conf:

    upstream backend {
        server backend:3000;
    }
    
    upstream frontend {
        server frontend:3000;
    }
    
    server {
        listen 80;
    
        location /api {
            proxy_pass http://backend;
        }
    
        location / {           
            proxy_pass http://frontend/;
        }
    }
    

    例如docker-compose.yml:

    version: '3.8'
    services:
      nginx:
        image: nginx:1.19.4
        depends_on:
          - server
          - frontend
        volumes:
          - ./nginx.conf:/etc/nginx/conf.d/default.conf
        ports:
          - '8080:80'
    

    然后确保您在 docker-compose 中将您的后端 dockerized 并调用(在这种情况下)backend 作为服务,并将前端(如果需要)作为服务调用 frontend:

    version: '3.8'
    services:    
      nginx:
        image: nginx:1.19.4
        depends_on:
          - server
          - frontend
        volumes:
          - ./default.conf:/etc/nginx/conf.d/default.conf
        ports:
          - '8080:80'
    
      frontend:
        build: ./frontend
    
      backend:
        build: ./backend
    

    这是一个最基本的入门示例。希望这对未来的开发者有所帮助。

    【讨论】:

      猜你喜欢
      • 2016-07-04
      • 2020-01-27
      • 1970-01-01
      • 2020-07-08
      • 2018-03-03
      • 2020-02-27
      • 2020-10-20
      • 2020-02-26
      • 1970-01-01
      相关资源
      最近更新 更多