Spring 引导应用无法在 docker 中 link 领事

Spring boot app fail to link consul in docker

我正在尝试使用 Consul 作为发现服务,另外两个 spring 引导应用程序向 Consul 注册;并将它们放入 docker;

以下是我的代码: 应用程序:

server:
  port: 3333

spring:
  application:
    name: adder
  cloud:
    consul:
      host: consul
      port: 8500
      discovery:
        preferIpAddress: true
        healthCheckPath: /health
        healthCheckInterval: 15s
        instanceId: ${spring.application.name}:${spring.application.instance_id:${server.port}}

2 docker-compose.yml

 consul1:
  image: "progrium/consul:latest"
  container_name: "consul1"
  hostname: "consul1"
  command: "-server -bootstrap -ui-dir /ui"
 adder:
  image: wsy/adder
  ports:
   - "3333:3333"
 links:
   - consul1
 environment:
   WAIT_FOR_HOSTS: consul1:8500

还有一个类似的问题; 答案表明,应用程序应该等待 consul 使用 depends_on 完全工作,我试过了,但没有用;

报错信息如下:

adder_1    | com.ecwid.consul.transport.TransportException: java.net.ConnectException: Connection refused
adder_1    |    at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:80) ~[consul-api-1.1.8.jar!/:na]
adder_1    |    at com.ecwid.consul.transport.AbstractHttpTransport.makeGetRequest(AbstractHttpTransport.java:39) ~[consul-api-1.1.8.jar!/:na]

除了spring boot application.yml和docker-compose.yml,下面是App的Dockerfile

FROM java:8

VOLUME /tmp
ADD adder-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'
ADD start.sh start.sh
RUN bash -c 'chmod +x /start.sh'
EXPOSE 3333
ENTRYPOINT ["/start.sh", " java -Djava.security.egd=file:/dev/./urandom    -jar /app.jar"]

和start.sh

#!/bin/bash

set -e

wait_single_host() {
  local host=
  shift
  local port=
  shift

  echo "waiting for TCP connection to $host:$port..."

  while ! nc ${host} ${port} > /dev/null 2>&1 < /dev/null
  do
    echo "TCP connection  [$host] not ready, will try again..."
    sleep 1
 done

  echo "TCP connection ready. Executing command [$host] now..."
}

 wait_all_hosts() {
  if [ ! -z "$WAIT_FOR_HOSTS" ]; then
   local separator=':'
   for _HOST in $WAIT_FOR_HOSTS ; do
      IFS="${separator}" read -ra _HOST_PARTS <<< "$_HOST"
      wait_single_host "${_HOST_PARTS[0]}" "${_HOST_PARTS[1]}"
    done
   else
     echo "IMPORTANT : Waiting for nothing because no $WAIT_FOR_HOSTS env var defined !!!"
   fi
  }

  wait_all_hosts

  exec 

你的问题是 depends_on 只控制你的服务的启动顺序。您必须等到 consul 服务器启动并且 运行 才能启动您的 spring 应用程序。您可以使用此脚本执行此操作:

#!/bin/bash

set -e

default_host="database"
default_port="3306"

host="${2:-$default_host}"
port="${3:-$default_port}"

echo "waiting for TCP connection to $host:$port..."

while ! (echo >/dev/tcp/$host/$port) &>/dev/null
do
  sleep 1
done

echo "TCP connection ready. Executing command [] now..."

exec 

您docker文件中的用法:

COPY wait.sh /wait.sh
RUN chmod +x /wait.sh
CMD ["/wait.sh", "java -jar yourApp-jar" , "consulURL" , "ConsulPort" ]

我只是想说明一下,我到最后还是没有解决办法,看不懂这里的情况;我尝试了 Ohmen 的建议,在 APP 容器中,我能够 ping consul1;但是APP还是连接不上consul;

如果我只通过以下命令启动 consul:

docker-compose -f docker-compose-discovery.yml up discovery

然后我可以直接运行这个APP(通过Main),它可以连接到spring.cloud.consul.host: discovery;

但是如果我尝试在 docker 容器中 运行 APP,如下所示:

docker run --name adder --link discovery-consul:discovery wsy/adder

再次失败,连接被拒绝;

我对 docker & docker-compose 很陌生;我认为这将是一个很好的开始示例,但对我来说似乎并不那么容易;

我可以推断出您的 Consul 配置位于您的 application.yml 而不是 bootstrap.yml,这就是问题所在。

根据 bootstrap.ymlapplication.yml 之前加载,Consul 客户端必须在应用程序本身之前检查其配置,因此查看 bootstrap.yml

工作示例 bootstrap.yml :

spring:
  cloud:
    consul:
      host: consul
      port: 8500
      discovery:
        prefer-ip-address: true
  1. 运行 Consul 服务器并且不要忘记 name 选项以匹配您的配置:

    docker run -d -p 8500:8500 --name=consul progrium/consul -server -bootstrap

  2. Consul 服务器现在 运行ning,运行 您的应用程序映像(之前使用您的工件构建)并且 link 它到 Consul 容器:

    docker run -d -name=my-consul-client-app --link consul:consul acme/spring-app