Docker-Compose --scale X Nginx.conf配置

16

我的nginx.conf文件目前直接定义了路由:

worker_processes auto;

events { worker_connections 1024; }

http {
    upstream wordSearcherApi {
          least_conn;

          server api1:61370 max_fails=3 fail_timeout=30s;
          server api2:61370 max_fails=3 fail_timeout=30s;
          server api3:61370 max_fails=3 fail_timeout=30s;
    }

    server {
          listen 80; 
          server_name server_name 0.0.0.0;

          location / {
              proxy_pass http://wordSearcherApi;
          }
    }
}

有没有办法在docker-compose.yml中只创建一个服务,并且在docker-compose up --scale api=3时,Nginx自动进行负载均衡?

2个回答

15

Nginx

Nginx支持动态上游(normal, sans Plus),但需要用一些技巧和有限制。

  1. 放弃使用upstream指令,改为使用普通的proxy_pass指令。

    这样可以实现轮询负载均衡和故障转移,但无法使用该指令的其他功能,如权重、故障模式、超时等。

  2. 必须通过变量传递上游主机名到proxy_pass并提供一个resolver

    这会强制Nginx重新解析主机名(针对Docker网络的DNS)。

  3. 失去了与location/proxy_pass相关的行为,例如末尾斜杠。

    如果是代理到裸的/,则无关紧要。否则,您必须手动rewrite路径(参见下面的引用)。

让我们看看它是如何工作的。

docker-compose.yml

version: '2.2'
services:
  reverse-proxy:
    image: nginx:1.15-alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    ports:
      - 8080:8080
  app:
    # A container that exposes an API to show its IP address
    image: containous/whoami
    scale: 4

nginx.conf

worker_processes  1;

events {
  worker_connections  1024;
}

http {
  access_log /dev/stdout;
  error_log /dev/stderr;

  server {
    listen 8080;
    server_name localhost;

    resolver 127.0.0.11 valid=5s;
    set $upstream app;

    location / {
      proxy_pass http://$upstream:80;
    }
  }
}

然后...

docker-compose up -d
seq 10 | xargs -I -- curl -s localhost:8080 | grep "IP: 172"

...会生成类似下面这样的内容,表明请求分布在4个app容器之间:

IP: 172.30.0.2
IP: 172.30.0.2
IP: 172.30.0.3
IP: 172.30.0.3
IP: 172.30.0.6
IP: 172.30.0.5
IP: 172.30.0.3
IP: 172.30.0.6
IP: 172.30.0.5
IP: 172.30.0.5

参考资料:

  1. 使用动态上游的Nginx
  2. 使用容器学习Nginx反向代理
  3. 用Python为Docker动态配置Nginx

Traefik

Traefik直接依赖于Docker API,可能是一种更简单和可配置的选择。让我们看看它的实际应用。

docker-compose.yml

version: '2.2'
services:
  reverse-proxy:
    image: traefik  
    # Enables the web UI and tells Traefik to listen to docker
    command: --api --docker  
    ports:
      - 8080:80      
      - 8081:8080  # Traefik's web UI, enabled by --api
    volumes:
      # So that Traefik can listen to the Docker events
      - /var/run/docker.sock:/var/run/docker.sock  
  app:
    image: containous/whoami
    scale: 4
    labels:
      - "traefik.frontend.rule=Host:localhost"

然后...

docker-compose up -d
seq 10 | xargs -I -- curl -s localhost:8080 | grep "IP: 172"

...还会生成一些输出,表明请求被分配到了 4 个 app 容器中:

IP: 172.31.0.2
IP: 172.31.0.5
IP: 172.31.0.6
IP: 172.31.0.4
IP: 172.31.0.2
IP: 172.31.0.5
IP: 172.31.0.6
IP: 172.31.0.4
IP: 172.31.0.2
IP: 172.31.0.5
在Traefik用户界面中(例如:http://localhost:8081/dashboard/),您可以看到它识别出4个app容器:

Backends

参考资料:
  1. Traefik快速入门(使用Docker)

4

由于您当前的配置是静态的,因此无法实现。您有两个选择:

1. 使用Docker引擎Swarm模式 - 您可以定义副本,Swarm内部DNS将自动平衡这些副本之间的负载。
参考文献 - https://docs.docker.com/engine/swarm/

2. 使用著名的Jwilder Nginx代理 - 该镜像侦听docker套接字,使用GO中的模板在扩展或缩小容器时动态更改nginx配置。
参考文献 - https://github.com/jwilder/nginx-proxy


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接