【问题标题】:docker-compose inter container communicationdocker-compose 容器间通信
【发布时间】:2019-03-07 14:15:20
【问题描述】:

我目前正在试验基于 Spring Boot 的微服务并开始使用 docker,但我遇到了障碍。

基本上我要做的是将 2 个小服务容器化:一个 spring 云配置服务和一个 spring 云 eureka 服务(发现服务)。 eureka 服务从 config 服务中获取其配置。

这两个服务都是独立的项目,都有自己的 Dockerfile:

Dockerfile-cloud-config-service:

FROM openjdk:10.0.2-13-jre-sid
ENV APP_FILE cloud-config-service.jar
ENV APP_HOME /usr/apps
EXPOSE 8888
COPY target/$APP_FILE $APP_HOME/
WORKDIR $APP_HOME
ENTRYPOINT ["sh", "-c"]
CMD ["exec java -jar $APP_FILE"]

Dockerfile-discovery-service:

FROM openjdk:10.0.2-13-jre-sid
ENV APP_FILE discovery-service.jar
ENV APP_HOME /usr/apps
EXPOSE 8761
COPY target/$APP_FILE $APP_HOME/
WORKDIR $APP_HOME
ENTRYPOINT ["sh", "-c"]
CMD ["exec java -jar $APP_FILE"]

使用 docker-compose 我正在尝试使用以下 docker-compose.yml 将它们联系在一起:

version: '3.7'
services:
  cloud-config-service:
    container_name: cloud-config-service
    build:
      context: cloud-config-service
      dockerfile: Dockerfile-cloud-config-service
    image: cloud-config-service:latest
    ports:
      - 8888:8888
    networks:
      - emp-network

  discovery-service:
    container_name: discovery-service
    build:
      context: discovery-service
      dockerfile: Dockerfile-discovery-service
    image: discovery-service:latest
    ports:
      - 8761:8761
    networks:
      - emp-network
    links:
      - cloud-config-service

networks:
  emp-network:
    driver: bridge

起初我将发现服务配置为从 http://localhost:8888 获取其配置,但经过一番挖掘后,我发现容器中的 localhost 指的是容器本身,并且在 Docker 文档中发现服务可以使用它们的名称相互引用。因此,我更改了发现服务的属性以从 http://cloud-config-service:8888 获取其配置。这不起作用,因此这篇文章。

两个 Dockerfile 的构建和运行都很好,除了发现服务无法在 http://cloud-config-service:8888 上获取配置服务这一事实。

如果我使用 host 网络驱动程序和 http://localhost:8888 端点,它确实有效,但是这“感觉”很老套,而不是应该如何完成。

我可能遗漏了一些微不足道的东西,但我恐怕找不到什么。

编辑: 发现服务控制台日志的小sn-p:

discovery-service       | 2018-10-02 13:14:26.798  INFO 1 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://cloud-config-service:8888
cloud-config-service    | 2018-10-02 13:14:26.836  INFO 1 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$8a18e3b3] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
discovery-service       | 2018-10-02 13:14:27.129  INFO 1 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://cloud-config-service:8888. Will be trying the next url if available
discovery-service       | 2018-10-02 13:14:27.129  WARN 1 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Could not locate PropertySource: I/O error on GET request for "http://cloud-config-service:8888/discovery-service/default": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)

【问题讨论】:

    标签: docker spring-boot docker-compose


    【解决方案1】:

    听起来你在正确的轨道上......我会引入depends_on 的概念来告诉容器discovery-service 在容器启动之前等待容器cloud-config-service 的启动

      discovery-service:
        container_name: discovery-service
        build:
          context: discovery-service
          dockerfile: Dockerfile-discovery-service
        image: discovery-service:latest
        depends_on:
          - cloud-config-service
        ports:
          - 8761:8761
        networks:
          - emp-network
        links:
          - cloud-config-service
    

    在容器能够主动处理流量之前启动容器需要一段有限的时间,因此最好注意这个启动顺序,尤其是在处理数据库容器时,其他人应该这样做depends_on

    【讨论】:

    • 感谢您的回复@scott-stensland。不幸的是,事实并非如此。最初我在 docker-compose.yml 中确实有一个 depends-on,直到我在 Docker Compose 文档中的links 中遇到以下段落:“链接也以与depends_on 相同的方式表达服务之间的依赖关系,因此它们确定顺序服务启动。”
    • 接下来我将不再提及网络...默认情况下它将启动一个桥接网络
    • 从 .yml 中删除了网络和每次提及它,但不幸的是无济于事。
    【解决方案2】:

    我无法发表评论,所以我正在写一个新答案。

    你有没有尝试运行类似docker exec -it myconatiner1 curl myconatiner2:port的东西

    查看它是否看到它或 ping,如果没有,是什么错误?

    【讨论】:

    • 感谢您的评论。事实证明,卷曲配置服务确实有效!我现在开始认为问题出在 Spring Cloud 查询属性文件中指定的地址的方式上。
    【解决方案3】:

    首先,docker 容器之间的通信是分布式服务中普遍存在的一个更大问题的一个子集 - 你不知道哪个服务(因此 their dependencies)会随时关闭,因此你应该考虑构建应用程序时出现此类故障。

    您面临的问题很常见,对于 Docker 容器更是如此,我相信容器间通信是 Docker 中的一个主要部分,它正在频繁地进行开发更改。

    为了解决你的问题,首先我想提出几点——

    1. 容器内的localhost 将引用该容器本身。
    2. 您机器上的localhost 实际上是指您的本地主机,并将与您通过ports 配置为docker-compose 文件中的每个服务映射的服务映射。
    3. depends_on 只等待容器启动,而不是等待实际进程开始运行——这可能意味着您等待的服务不一定已经启动并运行,因此会导致相关服务超时(s )。

    您需要等待服务开始运行,而不仅仅是容器启动。有两种可能的方法可以实现这一点 -

    1. 根据失败为您的 discovery-service 指定 restart 策略。在您的情况下,失败将是连接到cloud-config-service 时超时。 restart: on-failure:10 之类的东西,这意味着您要求 docker 在失败时重新启动 discover-service,最大重试次数为 10。这样,您将有合理的时间让其他容器(服务)启动并运行并制作确保具有重启策略的容器最终连接到那个容器。

    2. 使用另一个工具,例如 dockerize,它允许您在启动容器之前在其他服务上 wait

    此外,为确保您正确调试问题,请务必检查容器的日志以了解问题的真正原因 - docker logs -f --tail=100 <container_name/container_id>

    希望这会有所帮助。

    【讨论】:

    • 感谢您的评论。我将更深入地研究启动和依赖顺序。奇怪的是:按照@Niradnik 的建议执行docker exec curl 实际上会返回正确的配置。我开始认为问题出在 Spring Cloud 查询属性文件中指定的地址的方式上。
    • 我一直在努力解决类似的问题。 MySQL 和 Spring Boot 容器之间通过 docker-compose 进行通信。解决方案#1(重启:on-failure:10)对我有用。谢谢@graveti。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 2017-10-17
    相关资源
    最近更新 更多