无法使用Docker,Consul和nginx进行负载平衡 [英] Unable to load balance using Docker, Consul and nginx

查看:281
本文介绍了无法使用Docker,Consul和nginx进行负载平衡的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 版本:'2'
服务:
口音:
构建:
上下文:./accent
图像:口音
容器名称:口音
重新启动:总是
端口:
- 80
consul:
图像:gliderlabs / consul-server:最新
容器名:consul
主机名:$ {MYHOST}
重新启动:总是
端口:
- 8300: 8300
- 8400:8400
- 8500:8500
- 8600:53 / udp
命令:-advertise $ {MYHOST} -data-dir / tmp / consul -bootstrap - 客户端0.0.0.0
注册人:
图片:gliderlabs / registrator:最新
容器名:注册人
主机名:$ {MYHOST}
network_mode:主机
重新启动:总是
卷:
- /var/run/docker.sock:/tmp/docker.sock
命令:-ip $ {MYHOST} consul:// $ {MYHOST}:8500
nginx:
container_name:nginx
image:nginx:latest
resta rt:总是
卷:
- / etc / nginx
ports:
- 8181:80
consul-template:
container_name:consul-template
build:
上下文:./consul-template
network_mode:host
restart:always
volumes_from:
- nginx
volumes:
- /var/run/docker.sock:/tmp/docker.sock
命令:-consul = $ {MYHOST}:8500 -wait = 5s -template =/ etc / ctmpl / nginx.ctmpl: /etc/nginx/nginx.conf:docker kill -s HUP nginx

第一个服务 - 口音 - 是我的Web服务,我需要负载平衡。当我运行这个命令:

  $ docker-compose up 

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

  $ docker ps 

我在控制台中看到这个:

  ... NAMES STATUS PORTS 
consul-template Up 45秒
consul Up 56秒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上升41秒0.0.0.0:8181->80/tcp
注册商Up 56秒
重点加56秒0.0.0.0:32792->80/tcp

请注意最后一行,特别是PORTS列。您可以看到,此服务发布32792端口。要检查我的Web服务是否可以实现,请转到我的主机(运行docker组合的机器)上的 127.0.0.1:32972 ,然后在浏览器中看到: / p>

  Hello World 

这正是我想看到的。但是,这不是我终于想要的。请看看docker ps命令的输出,你会看到,我的nginx服务发布了8181端口。所以,我的期望是当我去这个地址 - 127.0.0.1:8181 - 我会看到完全相同的Hello world页面。但是,不是。在浏览器中,我看到坏网关错误消息,在nginx日志中我看到这个错误信息


nginx | 2017/01/18 06:16:45 [error] 5#5:* 5 connect()failed(111:Connection refused)while connection to upstream,client:172.18.0.1,server:,request:GET / favicon。 ico HTTP / 1.1,上游: http://127.0.0.1:32792/index.php,host:127.0.0.1:8181


真的很有趣,因为nginx会做我期望的 - 上游 http://127.0.0.1:32792/index.php 。但我不知道为什么会失败。顺便说一句,这是nginx.conf(使用领事馆模板自动创建)如下所示:

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

上游app_servers {
服务器127.0.0.1:32792;
}

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

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

位置〜\.php $ {
proxy_pass http:// app_servers;
proxy_redirect关闭;
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;
}

位置〜/\.ht {
拒绝所有;
}

}
}

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

  $ curl accent 
Hello World

$ curl 127.0.0.1:32972
curl:(7)无法连接到127.0.0.1端口32972:拒绝连接

$ curl口音:32972
curl:(7)无法连接到口音32972:连接拒绝

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

解决方案

当您进行端口绑定时,它会从容器发布一些端口(口音例如)和您的主机上的某些端口(随机 32792 在主机上 )。与您的口音容器相同的网络中的容器可以访问您的容器端口 80 口音(与口音:80 )由于docker-compose服务名称解析。您可以使用口音:32792 从您的主机访问口音:80 。当您从 nginx 容器中请求 127.0.0.1:32792 时,您只能访问 nginx 容器 32792 端口,而不是口音口音:32792 是不正确的URL( 80 端口打开口音 32792 在主机上)。但是当您将 nginx 容器添加到主机 127.0.0.1:32792 c $ c>网络。但是我注意到您在 curl 调用中使用不正确的端口。您的口音:80 发布到主持人 32792 ,但您要求 32972


What I want to achive is load balancing using this stack: Docker, Docker Compose, Registrator, Consul, Consul Template, NGINX and, finally, a tiny service that prints out "Hello world" in browser. So, at this moment I have a docker-compose.yml file. It looks like so:

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"

The first service - accent - is that my web service that I need to load balance. When I run this command:

$ docker-compose up

I see that all services start to run and I see no error messages. It looks as if everything is just perfect. When I run

$ docker ps

I see this in the console:

... 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

Please, pay attention to the last row and especially to PORTS column. As you can see, this service publishes 32792 port. To check that my web service is achievable I go to 127.0.0.1:32972 on my host machine (the machine where I run docker compose up) and see this in browser:

Hello World

This is exactly what I wanted to see. However, it is not what I finally want. Please, have a look at the output of docker ps command and you will see, that my nginx service published 8181 port. So, my expectation is that when I go to this address - 127.0.0.1:8181 - I will see exactly the same "Hello world" page. However, it is not. In browser I see Bad Gateway error message and in nginx logs I see this error message

nginx | 2017/01/18 06:16:45 [error] 5#5: *5 connect() failed (111: Connection refused) while connecting to upstream, client: 172.18.0.1, server: , request: "GET /favicon.ico HTTP/1.1", upstream: "http://127.0.0.1:32792/index.php", host: "127.0.0.1:8181"

It is really interesting, because nginx does what I expect it to do - upstreams to "http://127.0.0.1:32792/index.php". But I'm not sure why does it fail. By the way, this is how nginx.conf (created automatically with Consul Template) looks like:

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;
        }

    }
}

I wouldn't change anything, since this nginx.conf looks good to me. Trying to understand why it does not work, I shelled to nginx container and made a couple of commands:

$ 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

Again, it is interesting, because nginx container sees my web service under port 80 and not under its published 32972 port. Anyway, at this stage I do not know why it does not work and how to fix it. I just have a guess, that it is somehow connected to the way, how network is configured in docker-compose.yml. I tried various combinations of network_mode: host on accent and nginx service, but to no avail - either accent stops working or nginx or both. So, I need some help.

解决方案

When you do port binding it publish some port from container (80 in accent e.g.) and some port on your host (random 32792 on host e.g.).Containers in same network as your accent container can access your container port 80 by accent (same as accent:80) due to docker-compose services name resolving. You can access accent:80 from your host with accent:32792. When you are requesting 127.0.0.1:32792 from your nginx container you can access only nginx container 32792 port, not accent. accent:32792 is not correct url from anyway (80 port open on accent, 32792 on host). But 127.0.0.1:32792 should work when you add nginx container to host network. But I noticed that you use incorrect port in curl call. Your accent:80 published to host 32792 but you request 32972.

这篇关于无法使用Docker,Consul和nginx进行负载平衡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆