Spring Docker 容器中的云配置无法访问
Spring Cloud Config in Docker container is not accessible
我的设置相对简单。一个 Spring Could Config 服务器和一个 Spring Cloud Eureka 服务器。 (我在我的配置中将 Eureka 服务器称为发现无处不在...)配置服务器使用 Git 存储库来查找合适的配置。
一切都在 Docker 容器中。我使用 docker-compose 来构建我的服务。网关服务器应该等待配置服务器启动。我会在后面提供文件的来源。
因此,当我构建并启动容器时,发现 (Eureka) 服务器不想启动。它异常退出。真的很长,所以我只在这里添加最重要的部分:
019-01-27 23:52:17,494 [INFO ] o.s.c.c.c.ConfigServicePropertySourceLocator.getRemoteEnvironment [main] – Fetching config from server at : http://tao-elszamolas-config:9001
2019-01-27 23:52:17,898 [INFO ] o.s.c.c.c.ConfigServicePropertySourceLocator.getRemoteEnvironment [main] – Connect Timeout Exception on Url - http://tao-elszamolas-config:9001. Will be trying the next url if available
2019-01-27 23:52:17,902 [ERROR ] o.s.b.SpringApplication.reportFailure [main] – Application run failed
java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing
... Something...Something
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://tao-elszamolas-config:9001/discovery-server/prod": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:743) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:669) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:578) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.getRemoteEnvironment(ConfigServicePropertySourceLocator.java:218) ~[spring-cloud-config-client-2.1.0.RC3.jar!/:2.1.0.RC3]
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:96) ~[spring-cloud-config-client-2.1.0.RC3.jar!/:2.1.0.RC3]
... 15 more
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method) ~[?:?]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399) ~[?:?]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242) ~[?:?]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224) ~[?:?]
at java.net.Socket.connect(Socket.java:591) ~[?:?]
at java.net.Socket.connect(Socket.java:540) ~[?:?]
at sun.net.NetworkClient.doConnect(NetworkClient.java:182) ~[?:?]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:474) ~[?:?]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:569) ~[?:?]
at sun.net.www.http.HttpClient.<init>(HttpClient.java:242) ~[?:?]
at sun.net.www.http.HttpClient.New(HttpClient.java:341) ~[?:?]
at sun.net.www.http.HttpClient.New(HttpClient.java:362) ~[?:?]
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1242) ~[?:?]
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1181) ~[?:?]
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1075) ~[?:?]
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:1009) ~[?:?]
at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:734) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:669) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:578) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.getRemoteEnvironment(ConfigServicePropertySourceLocator.java:218) ~[spring-cloud-config-client-2.1.0.RC3.jar!/:2.1.0.RC3]
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:96) ~[spring-cloud-config-client-2.1.0.RC3.jar!/:2.1.0.RC3]
... 15 more
我在配置服务器日志中发现的唯一异常是抱怨与 Discovery (Eureka) 服务器的连接。是的,我尝试在 Eureka 中注册我的配置服务,以便在启动更多微服务时查找它。
连接被拒绝,这意味着当 Eureka 服务器试图获取其配置时,配置服务器不是 运行 或者它没有在给定端口 9001 上侦听。
怎么可能?我在我的撰写文件中使用了depends_on,所以它应该等待它。
或者为什么它完成了工作?如果我在没有 docker 的情况下在本地做同样的事情,那么它会一直尝试连接到 Config,直到配置服务器启动。我想使用 Docker.
实现相同的行为
如有任何建议,我们将不胜感激!
最后是我的配置文件:
docker-compose.yml:
version: "3"
services:
tao-elszamolas-config:
build: ./tao-elszamolas-config
container_name: tao-elszamolas-config
ports:
- "9001:9001"
volumes:
- "/tao-elszamolas/logs:/var/log/tao-elszamolas"
networks:
- taonetwork
tao-elszamolas-discovery:
build: ./tao-elszamolas-discovery
container_name: tao-elszamolas-discovery
depends_on:
- tao-elszamolas-config
ports:
- "9002:9002"
volumes:
- "/tao-elszamolas/logs:/var/log/tao-elszamolas"
networks:
- taonetwork
networks:
taonetwork:
driver: bridge
Docker配置服务器的文件:
FROM openjdk:11-jdk-slim
MAINTAINER BeszterceKK
COPY ./tao-elszamolas-config.jar /usr/src/taoelszamolas/tao-elszamolas-config.jar
WORKDIR /var/log/tao-elszamolas
WORKDIR /usr/src/taoelszamolas
ENV SPRING_PROFILES_ACTIVE prod
EXPOSE 9001
ENTRYPOINT ["java", "-DlogFileLocation=/var/log/tao-elszamolas", "-jar", "tao-elszamolas-config.jar"]
application.yml 配置服务器:
server:
port: 9001
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/something/something
username: something
password: something
skip-ssl-validation: true
security:
user:
name: something
password: something
eureka:
client:
serviceUrl:
defaultZone: http://something:something@tao-elszamolas-discovery:9002/eureka/
info:
artifact: tao-elszamolas-config
name: TAO Elszamolas Config Application
description: Tao elszamolas microservice elosztott szolgaltatas konfiguracio
version: 1.0.0
DockerDiscovery (Eureka) 服务器的文件:
FROM openjdk:11-jdk-slim
MAINTAINER BeszterceKK
COPY ./tao-elszamolas-discovery.jar /usr/src/taoelszamolas/tao-elszamolas-discovery.jar
WORKDIR /var/log/tao-elszamolas
WORKDIR /usr/src/taoelszamolas
ENV SPRING_PROFILES_ACTIVE prod
EXPOSE 9002
ENTRYPOINT ["java", "-DlogFileLocation=/var/log/tao-elszamolas", "-jar", "tao-elszamolas-discovery.jar"]
bootstrap.yml 对于 Discovery (Eureka) 服务器:
spring:
application:
name: discovery-server
cloud:
config:
fail-fast: true
name: discovery-server
uri: http://tao-elszamolas-config:9001
username: something
password: something
application.yml 对于 Discovery (Eureka) 服务器:
server:
port: 9002
eureka:
instance:
hostname: tao-elszamolas-discovery
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://tao-elszamolas-discovery:9002/eureka
info:
artifact: tao-elszamolas-discovery
name: TAO Elszamolas Eureka Szolgaltatas monitor
description: Tao elszamolas automatikus szolgaltatas regisztracio
version: 1.0.0
最后,这就是我启动容器的方式。就是:
docker-compose up -d
整个应用程序堆栈在没有 Docker 的情况下在本地工作。所以我想问题出在我的 Docker 配置上。
还有一件事要提,一般来说,我不想将端口发布到主机,只将它们暴露在容器之间的自定义网络上。这就是为什么我试图用 EXPOSE 替换 PORTS 但它并没有真正帮助。
for startup Compose does not wait until a container is “ready” (whatever that means for your particular application) - only until it’s running
所以,你应该参考:https://docs.docker.com/compose/startup-order/
for 等到配置服务器容器首先准备好(已经在端口 9001 上侦听),然后启动 Eureka 服务器容器。
您 registry
服务尝试在 configuration
服务启动之前启动。你必须强迫他等待。
您可以使用 condition: service_started
来完成,如下所示。但我认为它不适用于版本 3
version: '2.1'
# ...
tao-elszamolas-discovery:
build: ./tao-elszamolas-discovery
container_name: tao-elszamolas-discovery
depends_on:
- tao-elszamolas-config:
condition: service_started
ports:
- "9002:9002"
volumes:
- "/tao-elszamolas/logs:/var/log/tao-elszamolas"
networks:
- taonetwork
版本 3 的解决方案是使用 healthcheck
和 restart: on-failure
看看这个
另一种解决方案是使用 entrypoint
部分在启动时启动一个批处理文件,该文件正在 ping configuration
服务容器,但它没有响应。
我的设置相对简单。一个 Spring Could Config 服务器和一个 Spring Cloud Eureka 服务器。 (我在我的配置中将 Eureka 服务器称为发现无处不在...)配置服务器使用 Git 存储库来查找合适的配置。
一切都在 Docker 容器中。我使用 docker-compose 来构建我的服务。网关服务器应该等待配置服务器启动。我会在后面提供文件的来源。
因此,当我构建并启动容器时,发现 (Eureka) 服务器不想启动。它异常退出。真的很长,所以我只在这里添加最重要的部分:
019-01-27 23:52:17,494 [INFO ] o.s.c.c.c.ConfigServicePropertySourceLocator.getRemoteEnvironment [main] – Fetching config from server at : http://tao-elszamolas-config:9001
2019-01-27 23:52:17,898 [INFO ] o.s.c.c.c.ConfigServicePropertySourceLocator.getRemoteEnvironment [main] – Connect Timeout Exception on Url - http://tao-elszamolas-config:9001. Will be trying the next url if available
2019-01-27 23:52:17,902 [ERROR ] o.s.b.SpringApplication.reportFailure [main] – Application run failed
java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing
... Something...Something
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://tao-elszamolas-config:9001/discovery-server/prod": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:743) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:669) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:578) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.getRemoteEnvironment(ConfigServicePropertySourceLocator.java:218) ~[spring-cloud-config-client-2.1.0.RC3.jar!/:2.1.0.RC3]
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:96) ~[spring-cloud-config-client-2.1.0.RC3.jar!/:2.1.0.RC3]
... 15 more
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method) ~[?:?]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399) ~[?:?]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242) ~[?:?]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224) ~[?:?]
at java.net.Socket.connect(Socket.java:591) ~[?:?]
at java.net.Socket.connect(Socket.java:540) ~[?:?]
at sun.net.NetworkClient.doConnect(NetworkClient.java:182) ~[?:?]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:474) ~[?:?]
at sun.net.www.http.HttpClient.openServer(HttpClient.java:569) ~[?:?]
at sun.net.www.http.HttpClient.<init>(HttpClient.java:242) ~[?:?]
at sun.net.www.http.HttpClient.New(HttpClient.java:341) ~[?:?]
at sun.net.www.http.HttpClient.New(HttpClient.java:362) ~[?:?]
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:1242) ~[?:?]
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0(HttpURLConnection.java:1181) ~[?:?]
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:1075) ~[?:?]
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:1009) ~[?:?]
at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:734) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:669) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:578) ~[spring-web-5.1.3.RELEASE.jar!/:5.1.3.RELEASE]
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.getRemoteEnvironment(ConfigServicePropertySourceLocator.java:218) ~[spring-cloud-config-client-2.1.0.RC3.jar!/:2.1.0.RC3]
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:96) ~[spring-cloud-config-client-2.1.0.RC3.jar!/:2.1.0.RC3]
... 15 more
我在配置服务器日志中发现的唯一异常是抱怨与 Discovery (Eureka) 服务器的连接。是的,我尝试在 Eureka 中注册我的配置服务,以便在启动更多微服务时查找它。
连接被拒绝,这意味着当 Eureka 服务器试图获取其配置时,配置服务器不是 运行 或者它没有在给定端口 9001 上侦听。
怎么可能?我在我的撰写文件中使用了depends_on,所以它应该等待它。
或者为什么它完成了工作?如果我在没有 docker 的情况下在本地做同样的事情,那么它会一直尝试连接到 Config,直到配置服务器启动。我想使用 Docker.
实现相同的行为如有任何建议,我们将不胜感激!
最后是我的配置文件:
docker-compose.yml:
version: "3"
services:
tao-elszamolas-config:
build: ./tao-elszamolas-config
container_name: tao-elszamolas-config
ports:
- "9001:9001"
volumes:
- "/tao-elszamolas/logs:/var/log/tao-elszamolas"
networks:
- taonetwork
tao-elszamolas-discovery:
build: ./tao-elszamolas-discovery
container_name: tao-elszamolas-discovery
depends_on:
- tao-elszamolas-config
ports:
- "9002:9002"
volumes:
- "/tao-elszamolas/logs:/var/log/tao-elszamolas"
networks:
- taonetwork
networks:
taonetwork:
driver: bridge
Docker配置服务器的文件:
FROM openjdk:11-jdk-slim
MAINTAINER BeszterceKK
COPY ./tao-elszamolas-config.jar /usr/src/taoelszamolas/tao-elszamolas-config.jar
WORKDIR /var/log/tao-elszamolas
WORKDIR /usr/src/taoelszamolas
ENV SPRING_PROFILES_ACTIVE prod
EXPOSE 9001
ENTRYPOINT ["java", "-DlogFileLocation=/var/log/tao-elszamolas", "-jar", "tao-elszamolas-config.jar"]
application.yml 配置服务器:
server:
port: 9001
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/something/something
username: something
password: something
skip-ssl-validation: true
security:
user:
name: something
password: something
eureka:
client:
serviceUrl:
defaultZone: http://something:something@tao-elszamolas-discovery:9002/eureka/
info:
artifact: tao-elszamolas-config
name: TAO Elszamolas Config Application
description: Tao elszamolas microservice elosztott szolgaltatas konfiguracio
version: 1.0.0
DockerDiscovery (Eureka) 服务器的文件:
FROM openjdk:11-jdk-slim
MAINTAINER BeszterceKK
COPY ./tao-elszamolas-discovery.jar /usr/src/taoelszamolas/tao-elszamolas-discovery.jar
WORKDIR /var/log/tao-elszamolas
WORKDIR /usr/src/taoelszamolas
ENV SPRING_PROFILES_ACTIVE prod
EXPOSE 9002
ENTRYPOINT ["java", "-DlogFileLocation=/var/log/tao-elszamolas", "-jar", "tao-elszamolas-discovery.jar"]
bootstrap.yml 对于 Discovery (Eureka) 服务器:
spring:
application:
name: discovery-server
cloud:
config:
fail-fast: true
name: discovery-server
uri: http://tao-elszamolas-config:9001
username: something
password: something
application.yml 对于 Discovery (Eureka) 服务器:
server:
port: 9002
eureka:
instance:
hostname: tao-elszamolas-discovery
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://tao-elszamolas-discovery:9002/eureka
info:
artifact: tao-elszamolas-discovery
name: TAO Elszamolas Eureka Szolgaltatas monitor
description: Tao elszamolas automatikus szolgaltatas regisztracio
version: 1.0.0
最后,这就是我启动容器的方式。就是:
docker-compose up -d
整个应用程序堆栈在没有 Docker 的情况下在本地工作。所以我想问题出在我的 Docker 配置上。
还有一件事要提,一般来说,我不想将端口发布到主机,只将它们暴露在容器之间的自定义网络上。这就是为什么我试图用 EXPOSE 替换 PORTS 但它并没有真正帮助。
for startup Compose does not wait until a container is “ready” (whatever that means for your particular application) - only until it’s running
所以,你应该参考:https://docs.docker.com/compose/startup-order/
for 等到配置服务器容器首先准备好(已经在端口 9001 上侦听),然后启动 Eureka 服务器容器。
您 registry
服务尝试在 configuration
服务启动之前启动。你必须强迫他等待。
您可以使用 condition: service_started
来完成,如下所示。但我认为它不适用于版本 3
version: '2.1'
# ...
tao-elszamolas-discovery:
build: ./tao-elszamolas-discovery
container_name: tao-elszamolas-discovery
depends_on:
- tao-elszamolas-config:
condition: service_started
ports:
- "9002:9002"
volumes:
- "/tao-elszamolas/logs:/var/log/tao-elszamolas"
networks:
- taonetwork
版本 3 的解决方案是使用 healthcheck
和 restart: on-failure
看看这个
另一种解决方案是使用 entrypoint
部分在启动时启动一个批处理文件,该文件正在 ping configuration
服务容器,但它没有响应。