Docker服务注册到Consul但健康状况检查失败

时间:2016-05-19 16:01:30

标签: docker docker-compose docker-machine consul

我想将一个spring boot应用程序放在docker容器中。它使用@EnableDiscoveryClient,它将它与consul =>集成。登记和健康检查在码头工作之外完美地运作。

我使用此dockerfile嵌入了此示例应用程序(来自http://rpi-cloud.com/apigatewaypattern/的电影应用程序):

# 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)绑定到电影容器的localhost(使用docker network functionnality)。

它适用于服务发现:consul ui告诉我电影应用程序能够自我注册,但它不起作用:当领事服务试图达到电影服务的/健康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
领事开始很好,但电影服务无法注册=>拒绝连接。链接似乎对v2没有影响。因为https://github.com/docker/compose/issues/3127

/ etc / hosts不再提供

链接,它们现在由Docker 1.10.x中提供的嵌入式DNS服务器提供。打破了 localhost 技巧。

EDIT2

如果我为版本2明确设置了额外的主机(使用consul ip),它可以正常工作。

version: '2'

services:
  movie:
  # removed link keyword and replaced by
      extra_hosts:
        - "localhost:172.19.0.2"
  # specifying consul ip

EDIT3

这是版本2的电影容器看到的/ etc / hosts,但没有添加 extra_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的行为?

编辑4 - 结论

=>对于localhost技巧来说,这似乎是不可行的。所以我正在使用 docker中的其他配置(如建议的那样)。

这最终不是一个大问题,因为可以在Dockerfile的CMD中的命令行上覆盖默认的consul主机,然后我可以使用 consul 作为主机名。 (参见spring overload mechanism 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版本

我在带有docker-machine的Windows上使用docker 1.11.1

Docker版本1.11.1,build 5604cbe

docker-compose版本1.7.0,build 0d7bf73

1 个答案:

答案 0 :(得分:1)

由于您未使用撰写版本2.这两个容器不共享同一网络。

Consul执行定期运行状况检查以确保服务已启动并正在运行,因此需要访问应用程序运行状况检查服务。 这是“http://ca676cad169e:9000/health

由于您已经定义了从app容器到consul容器的链接,因此服务注册有效。该应用程序出现时会向领事注册。

您可以定义容器共享的网络,也可以在主机网络上运行容器。

您需要使用//variable to track handler status initially false $("#alert-unpublish-status").data("handler-added", false); $(document).on("click", ".check", function() { var status = $(this).closest("td").data("status"); var avatarID = $(this).closest("td").data("id"); if (status === 1) { $("#alert-unpublish-status").addClass('is-visible'); //check if handler is already added before adding again if (!$("#alert-unpublish-status").data("handler-added")) { $("#alert-unpublish-status").on("click", function(e) { e.preventDefault(); $.ajax({ url: 'https://www.legiaodossuperpoderes.com.br/chronus/api/adm/avatar/' + avatarID + '/unpublish', type: 'POST', contentType: "application/json; charset=UTF-8", xhrFields: { withCredentials: true }, success: function() { Materialize.toast("Avatar unpublished", 2000, "green darken-1"); $("#alert-unpublish-status").removeClass('is-visible'); setTimeout(loadPage, 500) } }); }); //sets variable so handler will not be added next time $("#alert-unpublish-status").data("handler-added", true); } } })选项

以下是文档的链接 https://docs.docker.com/compose/compose-file/#net

使用docker现有的docker compose版本,您可以更新电影应用程序的healthcheck端点。然后它将不使用默认值,并将在外部化端口上查询应用程序。

net: "host"

我尝试使用docker compose版本2并且可以通过两种方式访问​​容器,网络应该允许您以任何方式进行通信..在我的示例中,我使用consul容器下载了nginx页面。

spring:
  cloud:
    consul:
      discovery:
        healthCheckPath: localhost:9000/health
        healthCheckInterval: 15s