无法使用 Docker、Consul 和 nginx 进行负载平衡
Unable to load balance using Docker, Consul and nginx
我想要实现的是使用此堆栈的负载平衡: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"
第一个服务 - accent - 是我需要负载平衡的 Web 服务。当我 运行 这个命令时:
$ 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 服务是否可以实现,我转到主机上的 127.0.0.1:32972
(我 运行 docker 编写的机器)并在浏览器中看到:
Hello World
这正是我想看到的。然而,这并不是我最终想要的。请查看 docker ps 命令的输出,您会看到我的 nginx 服务发布了 8181 端口。所以,我的期望是,当我转到这个地址 - 127.0.0.1:8181
- 我会看到完全相同的 "Hello world" 页面。然而,事实并非如此。在浏览器中我看到 Bad Gateway 错误消息,在 nginx 日志中我看到这条错误消息
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"
这真的很有趣,因为 nginx 做了我期望它做的事情——upstreams 到“http://127.0.0.1:32792/index.php”。但我不确定为什么会失败。顺便说一句,这就是 nginx.conf(使用 Consul 模板自动创建)的样子:
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 中的网络配置方式。我在 accent 和 nginx 服务上尝试了 network_mode: host
的各种组合,但无济于事 - accent stops 工作或 nginx 或两者兼而有之。所以,我需要一些帮助。
当你进行端口绑定时,它会发布来自容器的一些端口(例如accent
中的80
)和你主机上的一些端口(例如主机上的随机32792
)。容器在由于 docker-compose 服务名称解析,与您的重音容器相同的网络可以通过 accent
(与 accent:80
相同)访问您的容器端口 80
。您可以使用 accent:32792
从主机访问 accent:80
。当您从 nginx
容器请求 127.0.0.1:32792
时,您只能访问 nginx
容器 32792
端口,不能访问 accent
。 accent:32792
无论如何都不正确 url(80
端口在 accent
、32792
主机上打开)。但是当您将 nginx
容器添加到 host
网络时,127.0.0.1:32792
应该可以工作。但我注意到您在 curl
调用中使用了不正确的端口。您的 accent:80
已发布到主机 32792
但您请求 32972
.
我想要实现的是使用此堆栈的负载平衡: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"
第一个服务 - accent - 是我需要负载平衡的 Web 服务。当我 运行 这个命令时:
$ 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 服务是否可以实现,我转到主机上的 127.0.0.1:32972
(我 运行 docker 编写的机器)并在浏览器中看到:
Hello World
这正是我想看到的。然而,这并不是我最终想要的。请查看 docker ps 命令的输出,您会看到我的 nginx 服务发布了 8181 端口。所以,我的期望是,当我转到这个地址 - 127.0.0.1:8181
- 我会看到完全相同的 "Hello world" 页面。然而,事实并非如此。在浏览器中我看到 Bad Gateway 错误消息,在 nginx 日志中我看到这条错误消息
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"
这真的很有趣,因为 nginx 做了我期望它做的事情——upstreams 到“http://127.0.0.1:32792/index.php”。但我不确定为什么会失败。顺便说一句,这就是 nginx.conf(使用 Consul 模板自动创建)的样子:
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 中的网络配置方式。我在 accent 和 nginx 服务上尝试了 network_mode: host
的各种组合,但无济于事 - accent stops 工作或 nginx 或两者兼而有之。所以,我需要一些帮助。
当你进行端口绑定时,它会发布来自容器的一些端口(例如accent
中的80
)和你主机上的一些端口(例如主机上的随机32792
)。容器在由于 docker-compose 服务名称解析,与您的重音容器相同的网络可以通过 accent
(与 accent:80
相同)访问您的容器端口 80
。您可以使用 accent:32792
从主机访问 accent:80
。当您从 nginx
容器请求 127.0.0.1:32792
时,您只能访问 nginx
容器 32792
端口,不能访问 accent
。 accent:32792
无论如何都不正确 url(80
端口在 accent
、32792
主机上打开)。但是当您将 nginx
容器添加到 host
网络时,127.0.0.1:32792
应该可以工作。但我注意到您在 curl
调用中使用了不正确的端口。您的 accent:80
已发布到主机 32792
但您请求 32972
.