Docker 服务正在注册到 Consul 但健康检查失败
Docker service registering into Consul but health check is failing
我想将 spring 引导应用程序放入 docker 容器中。它使用 @EnableDiscoveryClient 将其与 consul 集成 => 注册和健康检查在 docker.
之外完美运行
我将此示例应用程序(来自 http://rpi-cloud.com/apigatewaypattern/ 的电影应用程序)嵌入到此 docker 文件中:
# VERSION 1.0
FROM java:8
ADD ./movie-0.0.1-SNAPSHOT.jar /
# server port
EXPOSE 9000
WORKDIR /
CMD ["java", "-jar", "/movie-0.0.1-SNAPSHOT.jar"]
然后 运行 它来自以下 docker-compose.yml:
# service discovery
consul:
image: consul
ports:
- "8500:8500" # 8500 (HTTP)
command: agent -server -bootstrap-expect 1 -ui -data-dir /tmp -client=0.0.0.0
## test service
movie:
build: ./movie
ports:
- "9000:9000"
links:
- consul:localhost # for consul registry and configuration
如你所见,我试图变得聪明:为了避免将 consul 本身嵌入到电影容器中,我将 consul 主机 (ip) 绑定到电影容器的本地主机(使用 docker 网络功能)。
它非常适用于服务发现:consul ui 告诉我电影应用程序能够自行注册,但它不能以其他方式工作:当 consul 服务尝试到达 / 时,健康检查失败电影服务的健康 api。这是领事日志的输出:
2016/05/19 15:50:38 [INFO] agent: Synced service 'movie-9000'
及后者:
2016/05/19 15:50:43 [WARN] agent: http request failed 'http://ca676cad169e:9000/health': Get http://ca676cad169e:900
0/health: dial tcp: lookup ca676cad169e on 10.0.2.3:53: server misbehaving
无限重复。
我不明白为什么?有什么想法吗?
编辑
使用 docker-compose 版本 2 时:
version: '2'
services:
consul: ... (unchanged)
movie: ... (unchanged)
links:
- consul:localhost # for consul registry and configuration
consul 启动正常,但电影服务无法自行注册 => 连接被拒绝。链接似乎在 v2 中无效。因为 https://github.com/docker/compose/issues/3127
链接不再由 /etc/hosts 提供,它们现在由 Docker 中可用的嵌入式 DNS 服务器提供 1.10.x. 这打破了 localhost 技巧。
编辑2
如果我为版本 2(使用 consul ip)明确设置额外的主机,它工作正常。
version: '2'
services:
movie:
# removed link keyword and replaced by
extra_hosts:
- "localhost:172.19.0.2"
# specifying consul ip
编辑3
这是没有添加extra_hosts:
的版本2的电影容器看到的/etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.19.0.3 45210c319110
而在版本 1 中:
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
... # same +
172.17.0.2 localhost 88a07a35f228 ci_consul_1
如何在保持网络功能的同时自动执行并重新创建版本 1 的行为?
Edit4 - 结论
=> 这对于本地主机技巧来说似乎不可行。所以我回过头来使用
docker 中的不同配置(如建议的那样)。
这终于不是什么大问题了,因为可以在 Docker 文件的 CMD 中的命令行中覆盖默认的 consul 主机,然后我可以使用 consul 作为主机名。
(参见 spring 重载机制 http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html)
# in movie Dockerfile
CMD ["java", "-jar", "/movie-0.0.1-SNAPSHOT.jar", "--spring.cloud.consul.host=consul"]
Docker版本
我在 windows 上使用 docker 1.11.1 和 docker-machine
Docker 版本 1.11.1,build 5604cbe
docker-compose version 1.7.0, build 0d7bf73
因为您没有使用 compose 版本 2。这两个容器不共享同一个网络。
Consul 执行定期健康检查以确保服务正常运行 运行ning,因此需要访问应用程序健康检查服务。
这是“http://ca676cad169e:9000/health”
自从您定义了一个从应用程序容器到领事容器的 link 后,服务注册工作正常。该应用程序在启动时向 consul 注册。
您可以定义容器共享的网络,或者您可以 运行 主机网络上的容器。
您将需要使用 net: "host"
选项
这是文档的 link
https://docs.docker.com/compose/compose-file/#net
使用 docker 现有的 docker 撰写版本,您可以更新电影应用程序的健康检查端点。然后它将不使用默认值,并将在外部端口上查询应用程序。
spring:
cloud:
consul:
discovery:
healthCheckPath: localhost:9000/health
healthCheckInterval: 15s
我用 docker compose version 2 尝试了这个,并且可以两种方式访问容器,网络应该允许你以任何一种方式进行通信.. 在我的示例中,我使用 consul 容器下载了 nginx 页面。
version: "2"
services:
app:
image: nginx
ports:
- "9000:80"
discovery:
image: consul
ports:
- "8500:8500"
command: agent -server -bootstrap-expect 1 -ui -data-dir /tmp -client=0.0.0.0
docker version
Client:
Version: 1.10.3
API version: 1.22
Go version: go1.5.3
Git commit: 8acee1b
Built:
OS/Arch: linux/amd64
Server:
Version: 1.10.3
docker-compose version
docker-compose version 1.7.1, build 0a9ab35
docker-py version: 1.8.1
CPython version: 2.7.11
OpenSSL version: OpenSSL 1.0.2e 3 Dec 2015
我想将 spring 引导应用程序放入 docker 容器中。它使用 @EnableDiscoveryClient 将其与 consul 集成 => 注册和健康检查在 docker.
之外完美运行我将此示例应用程序(来自 http://rpi-cloud.com/apigatewaypattern/ 的电影应用程序)嵌入到此 docker 文件中:
# VERSION 1.0
FROM java:8
ADD ./movie-0.0.1-SNAPSHOT.jar /
# server port
EXPOSE 9000
WORKDIR /
CMD ["java", "-jar", "/movie-0.0.1-SNAPSHOT.jar"]
然后 运行 它来自以下 docker-compose.yml:
# service discovery
consul:
image: consul
ports:
- "8500:8500" # 8500 (HTTP)
command: agent -server -bootstrap-expect 1 -ui -data-dir /tmp -client=0.0.0.0
## test service
movie:
build: ./movie
ports:
- "9000:9000"
links:
- consul:localhost # for consul registry and configuration
如你所见,我试图变得聪明:为了避免将 consul 本身嵌入到电影容器中,我将 consul 主机 (ip) 绑定到电影容器的本地主机(使用 docker 网络功能)。
它非常适用于服务发现:consul ui 告诉我电影应用程序能够自行注册,但它不能以其他方式工作:当 consul 服务尝试到达 / 时,健康检查失败电影服务的健康 api。这是领事日志的输出:
2016/05/19 15:50:38 [INFO] agent: Synced service 'movie-9000'
及后者:
2016/05/19 15:50:43 [WARN] agent: http request failed 'http://ca676cad169e:9000/health': Get http://ca676cad169e:900
0/health: dial tcp: lookup ca676cad169e on 10.0.2.3:53: server misbehaving
无限重复。 我不明白为什么?有什么想法吗?
编辑 使用 docker-compose 版本 2 时:
version: '2'
services:
consul: ... (unchanged)
movie: ... (unchanged)
links:
- consul:localhost # for consul registry and configuration
consul 启动正常,但电影服务无法自行注册 => 连接被拒绝。链接似乎在 v2 中无效。因为 https://github.com/docker/compose/issues/3127
链接不再由 /etc/hosts 提供,它们现在由 Docker 中可用的嵌入式 DNS 服务器提供 1.10.x. 这打破了 localhost 技巧。
编辑2
如果我为版本 2(使用 consul ip)明确设置额外的主机,它工作正常。
version: '2'
services:
movie:
# removed link keyword and replaced by
extra_hosts:
- "localhost:172.19.0.2"
# specifying consul ip
编辑3
这是没有添加extra_hosts:
的版本2的电影容器看到的/etc/hosts127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.19.0.3 45210c319110
而在版本 1 中:
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
... # same +
172.17.0.2 localhost 88a07a35f228 ci_consul_1
如何在保持网络功能的同时自动执行并重新创建版本 1 的行为?
Edit4 - 结论
=> 这对于本地主机技巧来说似乎不可行。所以我回过头来使用 docker 中的不同配置(如建议的那样)。
这终于不是什么大问题了,因为可以在 Docker 文件的 CMD 中的命令行中覆盖默认的 consul 主机,然后我可以使用 consul 作为主机名。 (参见 spring 重载机制 http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html)
# in movie Dockerfile
CMD ["java", "-jar", "/movie-0.0.1-SNAPSHOT.jar", "--spring.cloud.consul.host=consul"]
Docker版本
我在 windows 上使用 docker 1.11.1 和 docker-machine
Docker 版本 1.11.1,build 5604cbe
docker-compose version 1.7.0, build 0d7bf73
因为您没有使用 compose 版本 2。这两个容器不共享同一个网络。
Consul 执行定期健康检查以确保服务正常运行 运行ning,因此需要访问应用程序健康检查服务。 这是“http://ca676cad169e:9000/health”
自从您定义了一个从应用程序容器到领事容器的 link 后,服务注册工作正常。该应用程序在启动时向 consul 注册。
您可以定义容器共享的网络,或者您可以 运行 主机网络上的容器。
您将需要使用 net: "host"
选项
这是文档的 link https://docs.docker.com/compose/compose-file/#net
使用 docker 现有的 docker 撰写版本,您可以更新电影应用程序的健康检查端点。然后它将不使用默认值,并将在外部端口上查询应用程序。
spring:
cloud:
consul:
discovery:
healthCheckPath: localhost:9000/health
healthCheckInterval: 15s
我用 docker compose version 2 尝试了这个,并且可以两种方式访问容器,网络应该允许你以任何一种方式进行通信.. 在我的示例中,我使用 consul 容器下载了 nginx 页面。
version: "2"
services:
app:
image: nginx
ports:
- "9000:80"
discovery:
image: consul
ports:
- "8500:8500"
command: agent -server -bootstrap-expect 1 -ui -data-dir /tmp -client=0.0.0.0
docker version
Client:
Version: 1.10.3
API version: 1.22
Go version: go1.5.3
Git commit: 8acee1b
Built:
OS/Arch: linux/amd64
Server:
Version: 1.10.3
docker-compose version
docker-compose version 1.7.1, build 0a9ab35
docker-py version: 1.8.1
CPython version: 2.7.11
OpenSSL version: OpenSSL 1.0.2e 3 Dec 2015