使用自定义 docker 网络的 2 个 dockerized spring boot 应用程序之间的通信

Posted

技术标签:

【中文标题】使用自定义 docker 网络的 2 个 dockerized spring boot 应用程序之间的通信【英文标题】:Communication between 2 dockerized spring boot applications using custom docker network 【发布时间】:2022-01-06 20:10:54 【问题描述】:

我有一个 Hello 服务和 World 服务。 Hello 服务有一个休息点 /hello/hw,它在内部调用 World 服务中的休息端点以返回字符串“Hello World”。 如果系统未 dockerized,则应用程序可以正常工作。

但是问题是当我想对系统进行 dockerize 时。 我使用 docker-compose 来容器化这两个服务。我在 docker compose 文件中定义了一个自定义网络(命名为 custom_net)。

rest端点/hello/hw可达,但Hello服务无法调用World服务中的rest端点。

Hello服务中的application.properties中World服务的url为http://localhost:8082/world

当我将 url 设置为 http://custom_net:8082/world 或 http://custom_net:8092/world 时,我得到 UnknownHostException

当我不更改 application.properties 中的 url 时,我收到 Connection denied 异常。 日志消息指出“失败:连接被拒绝:localhost/127.0.0.1:8082;” 我不确定桥接这 2 个服务需要什么配置

命令 docker network list 将自定义网络的名称显示为“tempfolder_custom_net”。 命令 docker inspect 显示 hello 和 world 服务都注册到了这个网络

version: '3'
services:
  hello_service:
    image: 'openjdk:8-jdk-alpine'
    restart: always
    container_name: hello_service
    volumes:
    - ./deploy:/root
networks:
- custom_net
depends_on:
- world_service
command: sh -c "java -jar -Dspring.config.location=file:///root/hello/application.yml  /root/hello/hello-0.0.1-SNAPSHOT.jar "
ports:
- 8091:8081

world_service:
image: 'openjdk:8-jdk-alpine'
restart: always
container_name: world_service
volumes:
- ./deploy:/root
command: sh -c "java -jar -Dspring.config.location=file:///root/world/application.yml  /root/world/world-0.0.1-SNAPSHOT.jar "
ports:
- 8092:8082
networks:
- custom_net

networks:
  custom_net:
    driver: bridge

Hello 服务的Application.yml ...

 server:
      port: 8081
    services:
      world:
        url: http://localhost:8082/world

【问题讨论】:

尝试拨打http://world_service:8092/world "http://world_service:8092/world" 给出连接被拒绝的异常。 "http://world_service:8082/world" 给出错误的请求 400 错误 你是如何从 hello service 调用 word service 的?如何在代码中配置 URL 调用?顺便说一句检查http://172.17.0.1:8092/world 在 Hello 服务中我使用的是 WebClient。 webClient 从 application.properties 获取基本 url。我不想硬编码IP。生产环境硬编码ip地址是标准做法吗? 能否分享 application.properties 文件中的 URL,并检查 http://172.17.0.1:8092/world 【参考方案1】:

@Thanh Nuguyen Van 感谢您提供有用的故障排除提示。 问题在于主机名 world_service。看起来下划线不是有效的 URL。下面是我更新的 docker compose 文件。我什至不必使用自定义 docker 网络。我将 application.yml 中的 url 更新为 http://worldservice:8082/world。 另请注意,端口是 8082 而不是 8092。我们必须提及应用程序的端口,而不是 docker 暴露的端口。

version: '3'
services:
  helloservice:
    image: 'openjdk:8-jdk-alpine'
    restart: always
    container_name: helloservice
    volumes:
    - ./deploy:/root
    #networks:
    #- custom_net
    depends_on:
    - worldservice
    command: sh -c "java -Xdebug -jar -Dspring.config.location=file:///root/hello/application.yml  /root/hello/hello-0.0.1-SNAPSHOT.jar "
    ports:
    - 8091:8081
  worldservice:
    image: 'openjdk:8-jdk-alpine'
    restart: always
    container_name: worldservice
    volumes:
    - ./deploy:/root
    command: sh -c "java -Xdebug -jar -Dspring.config.location=file:///root/world/application.yml  /root/world/world-0.0.1-SNAPSHOT.jar "
    ports:
    - 8092:8082
    #networks:
    #- custom_net
#networks:
  #custom_net:
    #driver: bridge

【讨论】:

【参考方案2】:

您应该在openjdk:8-jdk-alpine 图像基础上构建新图像,并添加入口点

你应该改变这个:

server:
      port: 8081
    services:
      world:
        url: http://localhost:8082/world

收件人:

server:
      port: 8081
    services:
      world:
        url: http://world_service:8092/world

确保两个容器都在运行。

【讨论】:

这并没有解决问题。我收到“连接被拒绝:worldservice/172.18.0.2:8092” 能否详细说明为什么需要使用新的图像库。我现有的图像库是相同的。还有什么需要在ENTRYPOINT中提到。命令还不够吗?我可以独立访问 Hello 服务和 World 服务 api Nuguyen Van 网址应为worldservice:8082/world。端口号应该是应用程序的,而不是 docker 暴露的端口,主机名应该是 worldservice(下划线去掉) 它是否适用于新配置? 是的。唯一的区别是没有使用自定义 docker 网络。

以上是关于使用自定义 docker 网络的 2 个 dockerized spring boot 应用程序之间的通信的主要内容,如果未能解决你的问题,请参考以下文章

Docker-----网络自定义网络容器通信跨主机容器通信

pipework原理解析

Docker——Docker网络(Network)+ 部署Redis高可用集群

Docker学习总结(62)——docker-compose.yml 详细说明

Docker学习总结(62)——docker-compose.yml 详细说明

docker-compose 网络问题