无法使用Docker,Consul和nginx加载平衡

时间:2017-01-18 06:46:10

标签: nginx docker load-balancing docker-compose consul-template

我想要实现的是使用此堆栈进行负载平衡:Docker,Docker Compose,Registrator,Consul,Consul Template,NGINX以及最后一个在浏览器中打印出“Hello world”的小型服务。所以,此刻我有一个docker-compose.yml文件。它看起来像这样:

version: '2'
services:
accent:
    build:
        context: ./accent
    image: accent
    container_name: accent
    restart: always
    ports:
        - 80
consul:
    image: gliderlabs/consul-server:latest
    container_name: consul
    hostname: ${MYHOST}
    restart: always
    ports:
        - 8300:8300
        - 8400:8400
        - 8500:8500
        - 8600:53/udp
    command: -advertise ${MYHOST} -data-dir /tmp/consul -bootstrap -client 0.0.0.0
registrator:
    image: gliderlabs/registrator:latest
    container_name: registrator
    hostname: ${MYHOST}
    network_mode: host
    restart: always
    volumes:
        - /var/run/docker.sock:/tmp/docker.sock
    command: -ip ${MYHOST} consul://${MYHOST}:8500
nginx:
    container_name: nginx
    image: nginx:latest
    restart: always
    volumes:
        - /etc/nginx
    ports:
        - 8181:80
consul-template:
    container_name: consul-template
    build:
        context: ./consul-template
    network_mode: host
    restart: always
    volumes_from:
        - nginx
    volumes:
        - /var/run/docker.sock:/tmp/docker.sock
    command: -consul=${MYHOST}:8500 -wait=5s -template="/etc/ctmpl/nginx.ctmpl:/etc/nginx/nginx.conf:docker kill -s HUP nginx"

第一项服务 - 口音 - 是我需要加载平衡的网络服务。当我运行此命令时:

$ docker-compose up

我看到所有服务都开始运行,我看不到任何错误消息。看起来好像一切都很完美。我跑的时候

$ docker ps

我在控制台中看到了这一点:

... NAMES              STATUS            PORTS
consul-template    Up 45 seconds     
consul             Up 56 seconds     0.0.0.0:8300->8300/tcp, 0.0.0.0:8400->8400/tcp, 8301-8302/tcp, 8301-8302/udp, 0.0.0.0:8500->8500/tcp, 8600/tcp, 8600/udp, 0.0.0.0:8600->53/udp    
nginx              Up 41 seconds     0.0.0.0:8181->80/tcp   
registrator        Up 56 seconds
accent             Up 56 seconds     0.0.0.0:32792->80/tcp

请注意最后一行,特别是PORTS栏。如您所见,此服务发布32792端口。要检查我的Web服务是否可以实现,请转到我的主机(运行docker compose up的机器)上的127.0.0.1:32972并在浏览器中查看:

Hello World

这正是我想要看到的。但是,这不是我最终想要的。请看看docker ps命令的输出,你会看到,我的nginx服务发布了8181端口。所以,我的期望是当我去这个地址 - 127.0.0.1:8181时 - 我会看到完全相同的“Hello world”页面。但事实并非如此。在浏览器中,我看到Bad Gateway错误消息,在nginx日志中,我看到此错误消息

  

nginx | 2017/01/18 06:16:45 [错误] 5#5:* 5连接()失败(111:连接被拒绝)连接上游,客户端:172.18.0.1,服务器:,请求:“GET / favicon。 ico HTTP / 1.1“,上游:”http://127.0.0.1:32792/index.php“,主持人:”127.0.0.1:8181“

这真的很有趣,因为nginx做了我期望它做的事情 - 上游到“http://127.0.0.1:32792/index.php”。但我不确定为什么会失败。顺便说一句,这就是nginx.conf(使用Consul Template自动创建)的样子:

worker_processes 1;
events {
    worker_connections 1024;
}
http {
    sendfile on;

    upstream app_servers {
        server 127.0.0.1:32792;
    }

    server {
        listen 80;
        root /code;
        index index.php index.html;

        location / {
            try_files $uri/ $uri/ /index.php;
        }

        location ~ \.php$ {
         proxy_pass http://app_servers;
         proxy_redirect off;
         proxy_set_header Host $host;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header X-Forwarded-Host $server_name;
        }

        location ~ /\.ht {
        deny all;
        }

    }
}

我不会改变任何东西,因为这个nginx.conf看起来不错。试图理解为什么它不起作用,我炮轰到nginx容器并做了几个命令:

$ curl accent
Hello World

$ curl 127.0.0.1:32972
curl: (7) Failed to connect to 127.0.0.1 port 32972: Connection refused

$ curl accent:32972
curl: (7) Failed to connect to accent port 32972: Connection refused

同样,有趣的是,因为nginx容器在端口80下看到我的Web服务,而不在其发布的32972端口下。无论如何,在这个阶段我不知道为什么它不起作用以及如何解决它。我只是猜测,它以某种方式连接到方式,如何在docker-compose.yml中配置网络。我在重音和nginx服务上尝试了network_mode: host的各种组合,但无济于事 - 重音停止工作或nginx或两者兼而有之。所以,我需要一些帮助。

1 个答案:

答案 0 :(得分:1)

当你进行端口绑定时,它会从容器(例如80中的accent)和主机上的某个端口(主机上的随机32792)发布一些端口。同一网络中的容器由于docker-compose服务名称解析,您的重音容器可以通过80(与accent相同)访问您的容器端口accent:80。您可以使用accent:80从主机访问accent:32792。当您从127.0.0.1:32792容器中请求nginx时,您只能访问nginx容器32792端口,而不能访问accent。无论如何accent:32792都不是正确的网址(80端口在accent上打开,32792在主机上打开。但是,当127.0.0.1:32792容器添加到nginx网络时,host应该有效。但我注意到你在curl电话中使用了错误的端口。您的accent:80已发布到托管32792,但您请求32972