【问题标题】:nginx reverse proxy with docker - load balancing带有 docker 的 nginx 反向代理 - 负载平衡
【发布时间】:2017-05-26 07:53:09
【问题描述】:

我想使用 Docker 技术对 nginx 作为反向代理进行简单的配置。我正在考虑使用这个解决方案:https://hub.docker.com/r/jwilder/nginx-proxy/

我需要实现以下行为:

->当请求到达 www.example.com 时,它将转到容器 A

->当请求到达www.example.com/part时,它会转到容器B(不同的容器)

我不太擅长 Nginx 服务器配置。我知道,在运行我需要代理的其他容器时,我需要传递 VIRTUAL_HOST、VIRTUAL_PORT 变量,但我不知道要调整什么或传递什么才能强制 nginx 服务器根据位置切换流量。是 Nginx 服务器及其位置指令的问题还是其他需要调整的问题?

提前感谢您在此花费的宝贵时间和精力。

所以这里是这个问题的更新 - 希望我能更准确地描述我的问题所在。嗯,我已经在这方面花了很多时间,另一件事是我只能在没有人使用系统的晚上玩配置。

我们的环境中有 Docker 守护程序在 RHEL7 (Maipo 7.3) 上运行。我们有几个 docker 容器,其中一个是基于镜像 mkodockx/docker-nginx-proxy:stable 的容器。请参阅下面的配置文件 - 基本思想是使用开关 -e VIRTUAL_HOST=some_host 运行每个图像。

我认为我需要找到一种方法来传递另一个环境变量来创建正确的位置指令;我正在调整图像中 /app 目录中的 nginx.tmpl。

请看配置文件:

# Generated nginx site conf                        
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
  default $http_x_forwarded_proto;
  ''      $scheme;
}
map $http_upgrade $proxy_connection {
  default upgrade;
  '' close;
}

gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent"';
access_log off;
error_log /proc/self/fd/2;
client_max_body_size 10m;
proxy_http_version 1.1;
proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
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 $proxy_x_forwarded_proto;

server {
        listen 80 default_server;
        server_name _;
        return 503;
}      
upstream A.B.C.com {    
    server 172.17.0.7:8080;    
}        
server {
    limit_conn perip 50;
    limit_req zone=persec burst=80 nodelay;
    server_name A.B.C.com; 
    location / {
            proxy_pass http://A.B.C.com; 
    }
}        
upstream D.E.F.com {    
    server 172.17.0.16:8080;    
}        
server {
    limit_conn perip 50;
    limit_req zone=persec burst=80 nodelay;
    server_name D.E.F.com; 
    location / {
            proxy_pass http://D.E.F.com; 
    }
}        
upstream G.H.I.com {    
    server 172.17.0.8:80;    
}        
server {
    limit_conn perip 50;
    limit_req zone=persec burst=80 nodelay;
    server_name G.H.I.com; 
    location / {
            proxy_pass http://G.H.I.com; 
    }
}        
upstream J.K.L.com {    
    server 172.17.0.5:80;    
}        
server {
    limit_conn perip 50;
    limit_req zone=persec burst=80 nodelay;
    server_name J.K.L.com; 
    location / {
            proxy_pass http://J.K.L.com; 
    }
}        
upstream M.N.O.com {    
    server 172.17.0.6:80;    
}        
server {
    limit_conn perip 50;
    limit_req zone=persec burst=80 nodelay;
    server_name M.N.O.com; 
    location / {
            proxy_pass http://M.N.O.com; 
    }
}   

这是我的步骤:

1) 我使用 docker exec -it proxy bash 登录到容器

2) 然后我调整了 nginx.tmpl 文件 - 使用 vim

3) 然后我在容器中运行 forego start -r 命令

4) 然后我检查了生成的 default.conf 文件 - Nginx 已自动重启

5) 然后我尝试验证 URL

我的问题是我需要以某种方式从 URL 提供其内容的另一个容器,比如说 D.E.F.com/schedule;当前的 nginx.tmpl 模板只会添加内部容器的 IP (172.x.x.x:80) 并创建另一个服务器块/部分;我无法指定位置部分。

所以我提出了我的解决方案(新的 nginx 模板),它可以指定(传递)另一个变量。但最后仍然发生的是,新容器的所有内容都是从根(“/”)而不是 /schedule 部分提供的。然而,从 URL D.E.F.com 提供内容的现有容器实际上在 URL D.E.F.com/content 上具有其内容 - 但正如您所见,该位置未在生成的 nginx 配置中指定。两台服务器都会自动添加到同一个上游部分。但这意味着,至少根据文档,会有一种负载平衡,这不是这里所期望的。我在这里迷路了。

那么我在这里忽略了什么或有什么问题?

再次感谢您在这方面花费时间和精力。

【问题讨论】:

    标签: nginx docker proxy reverse-proxy


    【解决方案1】:

    它与 Nginx 配置非常相关。使用官方 Nginx Docker 镜像,您需要添加 Nginx 配置,例如:

    server {
       listen 80 default_server;
       listen [::]:80 default_server;
    
       server_name www.example.com;
    
       location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
    
                proxy_pass http://container_A:80;
        }
    }
    

    server {
       listen 80 default_server;
       listen [::]:80 default_server;
    
       server_name www.example.com;
    
       location /part {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
    
                proxy_pass http://container_B:80;
        }
    }
    

    这里比较棘手的是主机container_Acontainer_B。这是由--name container_A--name container_B 标志表示的两个容器,您必须用户定义的网络中运行它们,首先通过docker network create <name-of-the-network> 创建一个Docker 网络并通过指定在同一个 Docker 网络中运行每个容器:

    docker run .... --network=<name-of-the-network> ....

    Docker Engine 中的服务发现功能会发现用户自定义网络中的主机container_Acontainer_BHere 就是一个例子。

    【讨论】:

    • 嗯,谢谢你的回答。我最大的问题是我想运行/启动一个新容器,它应该动态处理对 www.example.com/part 的请求 - 即像 -e VIRTUAL_HOST=www.example.com/part 一样传递它,但我是不确定这是否可能...?
    • 是的,有可能,只要确保您在单独的 Docker 网络中运行每个容器,并且仅从该网络公开 nginx 服务 的端口。
    • 好吧,抱歉,我正在努力解决这个问题。我可以根据需要调整 docker-gen 的 nginx.tmpl 文件以添加更多环境变量;我在尝试指定位置部分的地方添加 VIRTUAL_PATH - 在我的情况下是“/part”。所以我最终不得不使用不同的位置设置服务器块,但它仍然无法正常工作。我找不到原因。
    • 我已经更新了我的问题,希望它能带来更多的启发,我会知道出了什么问题。
    • 所以让我知道我已经弄清楚了。您希望有 2 个容器在根目录上侦听,但实际内容是从根目录以外的 URL 提供的,并且您想在它们到达端口 80 时通过 Nginx 配置将它们重定向?
    猜你喜欢
    • 1970-01-01
    • 2018-09-24
    • 2017-12-11
    • 1970-01-01
    • 2023-04-04
    • 2022-01-03
    • 2018-12-12
    • 1970-01-01
    • 2016-11-08
    相关资源
    最近更新 更多