如何在Docker Compose中创建多个Java应用副本实现Ribbon负载均衡?
实现方案
核心思路
本方案仅使用docker-compose原生的服务定义能力,未引入K8s、Swarm等额外编排工具,无需构建多份镜像,具体逻辑如下:
- 利用Docker容器网络的隔离特性,多个容器的内部端口互不冲突,所有副本可直接使用镜像内置的
server.port=8000配置,无需修改 - 同一镜像在docker-compose中定义为3个独立服务,按需配置不同的宿主机端口映射即可对外暴露,无需对外暴露的场景可直接省略端口配置
- Ribbon作为客户端负载均衡组件,会自动拉取注册中心的全量可用实例列表,无需额外修改配置即可实现请求分发
完整docker-compose.yml配置示例
version: '3.8' services: # 可选:如果使用Eureka作为注册中心,可一并配置 eureka-server: image: eureka-server:latest # 替换为实际的Eureka镜像名称 ports: - "8761:8761" networks: - ribbon-app-network # 第一个服务副本 service-demo-1: image: spring-ribbon-app:latest # 替换为实际的Spring应用镜像名称,三个副本使用完全相同的镜像 ports: - "8001:8000" # 宿主机8001映射到容器内部8000,无需对外暴露可删除本行 environment: # 替换为实际的注册中心地址,docker-compose内部可直接用服务名访问 - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://eureka-server:8761/eureka/ networks: - ribbon-app-network restart: unless-stopped # 第二个服务副本 service-demo-2: image: spring-ribbon-app:latest ports: - "8002:8000" # 宿主机8002映射到容器内部8000 environment: - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://eureka-server:8761/eureka/ networks: - ribbon-app-network restart: unless-stopped # 第三个服务副本 service-demo-3: image: spring-ribbon-app:latest ports: - "8003:8000" # 宿主机8003映射到容器内部8000 environment: - EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://eureka-server:8761/eureka/ networks: - ribbon-app-network restart: unless-stopped networks: ribbon-app-network: driver: bridge
适配说明
- 如果没有使用注册中心,采用静态Ribbon服务列表配置,只需要修改应用的
application.properties即可:
# 替换为实际的服务名,列表填写docker-compose中三个服务的内部访问地址 demo-service.ribbon.listOfServers=http://service-demo-1:8000,http://service-demo-2:8000,http://service-demo-3:8000
- 如果确实需要修改容器内部的端口,可通过
command参数覆盖Spring Boot配置,无需重新构建镜像,示例:
service-demo-1: image: spring-ribbon-app:latest command: java -jar /app.jar --server.port=8001 # 替换为实际的jar包路径和端口 ports: - "8001:8001"
启动验证
- 执行
docker-compose up -d即可启动全部服务 - 执行
docker-compose ps可查看三个副本的运行状态和端口映射关系 - 多次调用Ribbon客户端接口,查看服务日志可验证负载均衡已经生效
内容的提问来源于stack exchange,提问作者Appaul
相关产品推荐
相关产品推荐

