Docker service registering into Consul but health check is failing
Answer a question I want to put a spring boot application inside a docker container. It uses @EnableDiscoveryClient which integrate it with consul => registration and health check are working perfectl
Answer a question
I want to put a spring boot application inside a docker container. It uses @EnableDiscoveryClient which integrate it with consul => registration and health check are working perfectly outside of docker.
I embeded this sample application (movie app from http://rpi-cloud.com/apigatewaypattern/ ) with this dockerfile:
# 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"]
And then run it from the following 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
As you can see I tried to be smart: to avoid embedding consul itself into the movie container I have bind the consul host (ip) to localhost of movie container (using docker network functionnality).
It works for well for service discovery : consul ui show me that movie application was able to register itself, but it does not work the other way: health check is failing when consul service try to reach /health api of movie service. Here is an output from the consul logs:
2016/05/19 15:50:38 [INFO] agent: Synced service 'movie-9000'
and latter:
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
which repeat itself indefinitely. I don't understand why ? Any idea ?
Edit When using docker-compose version 2:
version: '2'
services:
consul: ... (unchanged)
movie: ... (unchanged)
links:
- consul:localhost # for consul registry and configuration
consul start fine, but movie service fail to register itself => connection refused. links seems to have no effect in v2. because https://github.com/docker/compose/issues/3127
links are no longer provided by /etc/hosts, they are now provided by an embedded DNS server available in Docker 1.10.x. which breaks the localhost trick.
Edit2
If I explicitly set additional host for version 2 (with consul ip) it works fine.
version: '2'
services:
movie:
# removed link keyword and replaced by
extra_hosts:
- "localhost:172.19.0.2"
# specifying consul ip
Edit3
this is the /etc/hosts seen by the movie container with version 2 without adding 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
whereas in version 1:
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
... # same +
172.17.0.2 localhost 88a07a35f228 ci_consul_1
How can I to automate that and recreate behavior of version 1, while keeping network feature ?
Edit4 - conclusion
=> this seems unfeasible for the localhost tricks. So am falling back using a different configuration in docker (as suggested).
This is finally not a big issue because the default consul host can be overridden on the command line within the CMD of the Dockerfile, and then I can use consul as the hostname. (see 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 version
I am using docker 1.11.1 on windows with docker-machine
Docker version 1.11.1, build 5604cbe
docker-compose version 1.7.0, build 0d7bf73
Answers
Since you are not using compose version 2. The two containers do not share the same network.
Consul executes periodic health checks to ensure the service is up and running and hence needs access to the application healthcheck service. Which is "http://ca676cad169e:9000/health"
The registration of service works since you have defined a link from app container to the consul container. The app registers itself with consul when it comes up.
You can define a network which is shared by the containers or you can run the containers on the host network.
You will need to use net: "host"
option
Here is the link to the documentation https://docs.docker.com/compose/compose-file/#net
With docker the existing docker compose version, you can update the healthcheck endpoint of the movie app. It will then not use the defaults and will query the app on externalized port.
spring:
cloud:
consul:
discovery:
healthCheckPath: localhost:9000/health
healthCheckInterval: 15s`
I tried this with docker compose version 2 and could access containers both ways, The networking should allow you to communicate either ways.. in my sample I downloaded nginx page from with consul container.
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
更多推荐
所有评论(0)