带有docker的nginx反向代理 - 负载均衡

时间:2017-05-26 07:53:10

标签: nginx docker proxy reverse-proxy

我想使用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服务器及其位置指令的问题还是其他需要调整的问题?

提前感谢您在这里度过的宝贵时间和精力。

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

我们的环境中有在RHEL7(Maipo 7.3)上运行的Docker守护程序。我们有几个docker容器,其中一个是基于image mkodockx / docker-nginx-proxy:stable的容器。请参阅下面的配置文件 - 基本思路是使用switch -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提供其内容,让我们说 D.E.F.com/schedule ;当前的nginx.tmpl模板只会添加内部容器的IP(172.x.x.x:80)并创建另一个服务器块/部分;我无法指定位置部分。

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

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

再一次,非常感谢你花时间和精力在这上面。

1 个答案:

答案 0 :(得分: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标志代表的2个容器,您首先通过创建Docker网络必须用户定义的网络中运行它们通过docker network create <name-of-the-network>并通过指定:

在同一个Docker网络中运行每个容器

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

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