Docker Compose部署SpringBoot微服务无法注册到Eureka问题
问题根因
注册失败本质是Docker网络隔离导致的:
- 直接执行
docker run启动的容器默认会加入Docker自带的bridge网络,你之前独立部署的Eureka Server、测试用的sap-listener服务都在这个网络里,所以可以通过Eureka的容器内部IP172.17.0.2:8761正常连通。 - 用docker-compose启动服务栈时,会默认创建一个独立的自定义隔离网络,栈内的mysql、phpmyadmin、ldap-app都在这个隔离网络里,和Eureka所在的默认
bridge网络不互通,自然访问不到172.17.0.2这个地址,才会报连接超时。
另外你硬编码容器内部IP的方式本身就不稳定,只要Eureka容器重启,内部IP就会重新分配,后续也会出现注册失败的问题。
解决方案
不需要把已经独立部署的Eureka迁到compose配置里,根据实际场景二选一即可。
方案一:网络打通(推荐,不需要调整Eureka端口映射)
将compose栈中需要注册Eureka的服务,同时加入Eureka所在的外部网络,既保留compose内部服务的连通性,又能访问独立部署的Eureka:
- 先确认Eureka所在的网络名,执行以下命令查询(默认独立docker run启动的容器网络名就是
bridge):
docker inspect 你的Eureka容器名称 --format '{{range $k,$v := .NetworkSettings.Networks}}{{$k}}{{end}}'
- 修改原docker-compose.yml配置,增加网络声明,并给需要访问Eureka的服务挂载对应网络,同时通过环境变量覆盖硬编码的Eureka地址,改用Docker内置DNS解析的容器名访问(避免IP变动问题):
version: "3.3" services: docker-mysql: image: mysql restart: always environment: MYSQL_ROOT_PASSWORD: 'password' MYSQL_DATABASE: 'db' ports: - "3007:3306" phpmyadmin: image: phpmyadmin restart: always container_name: php-my-admin-users ports: - "8081:80" ldap-app: image: myRepo/service1:latest ports: - "8090:8090" environment: SPRING_DATASOURCE_URL: jdbc:mysql://docker-mysql:3306/db # 替换为你实际的Eureka容器名,同网络下Docker DNS会自动解析到对应容器IP EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://你的Eureka容器名:8761/eureka depends_on: - docker-mysql networks: - default - eureka-net # 声明网络 networks: default: external: false eureka-net: external: name: bridge # 替换为第一步查询到的Eureka所在网络名
- 重新执行
docker-compose -f docker-compose.yml up -d启动服务栈即可正常注册。
方案二:通过宿主机IP访问(配置更简单)
如果你部署Eureka的时候已经做了端口映射,也就是启动Eureka时加了-p 8761:8761参数把Eureka端口映射到了宿主机,那不需要调整Docker网络,直接把Eureka注册地址改成宿主机的内网物理IP即可:
- 先查询生产环境宿主机的内网IP(比如192.168.x.x、10.x.x.x这类内网地址,不要用127.0.0.1,容器内的127.0.0.1指向容器自身)。
- 在compose的ldap-app服务的environment配置段里,增加Eureka地址覆盖配置:
environment: SPRING_DATASOURCE_URL: jdbc:mysql://docker-mysql:3306/db # 替换为实际的宿主机内网IP EUREKA_CLIENT_SERVICEURL_DEFAULTZONE: http://宿主机内网IP:8761/eureka
- 重启compose服务栈即可,compose创建的默认网络是允许容器访问宿主机IP的。
注意:如果是测试环境用Windows/Mac版本Docker,可以直接用特殊域名
host.docker.internal代替宿主机IP访问宿主机服务,生产Linux环境建议直接用宿主机实际内网IP,兼容性最好。
内容的提问来源于stack exchange,提问作者Pickeroll
相关产品推荐
相关产品推荐

