docker 的 nginx 反向代理 - 负载平衡

nginx reverse proxy with docker - load balancing

我想使用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 守护进程 运行ning 在 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) 然后我 运行 放弃容器中的 start -r 命令

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

5) 然后我尝试验证 URLs

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

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

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

再次感谢您为此花费时间和精力。

跟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 标志表示的 2 个容器,您 必须 运行 它们在 用户定义的网络 通过首先通过 docker network create <name-of-the-network> 创建一个 Docker 网络,并且 运行 每个容器在同一个 Docker 网络中指定:

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

Docker引擎中的服务发现功能将发现用户定义网络中的主机container_Acontainer_BHere 是一个例子。