Docker nginx 代理到主机

Posted

技术标签:

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

简短说明:

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

详细说明:

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

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

我正在寻找的是:

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

提前致谢。

【问题讨论】:

【参考方案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 "";
        
    
 

【讨论】:

host.docker.internal 看起来它在 linux 上不受支持 github.com/docker/for-linux/issues/264【参考方案4】:

有几点需要注意:

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

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

【讨论】:

以上是关于Docker nginx 代理到主机的主要内容,如果未能解决你的问题,请参考以下文章

Nginx反向代理docker容器进行域名解析绑定的实现方法

Docker安装的Nginx如何代理宿主机的服务

docker nginx 代理宿主机服务

NGINX 反向代理到运行 Web 应用程序的 docker 容器

对 docker 容器使用 nginx 反向代理

为Docker创建自动化nginx反向代理