SpringCloud 进阶篇①:微服务容器化部署(Docker+Compose 一键编排)
大家好,前九篇我们已经搭建了一个 “高可用、高并发、可管理、可排查、高安全、可观测” 的生产级微服务基础集群:通过 Nacos 实现配置的统一管理与加密,通过 OpenFeign+Ribbon 实现服务通信与负载均衡,通过 Resilience4j 实现贴合业务的降级兜底,通过 Spring Cloud Gateway 实现统一入口管控,通过 Sleuth+Zipkin+ELK 实现链路追踪与日志集中收集,通过 Spring Boot Admin 实现实时监控告警。但在实际落地过程中,还存在一个核心痛点:微服务部署繁琐—— 本地开发时需要逐个启动 Nacos、ES、Kibana、Filebeat、多个微服务,步骤多且易出错;服务器部署时环境配置不一致,导致 “本地能跑、服务器报错”。今天就聚焦微服务 “服务编排” 核心需求,手把手教大家用 Docker+Compose 实现微服务容器化部署,一键启动所有服务,解决环境不一致、部署繁琐的痛点,全程实操,新手跟着走就能掌握!
温馨提示:实操前请确认前提(避免踩坑):
① 已完成前九篇实操,所有微服务能本地正常运行;
② 版本保持一致:Spring Boot 2.6.13 + Spring Cloud Hoxton.SR12 + Nacos 2.0.7 + Docker 20.10.x + Docker Compose 2.20.x;
③ 已安装 Docker Desktop(Windows/Mac)或 Docker 引擎(Linux),并确保 Docker 正常运行;④ 重点注意:容器化核心是 “镜像构建 + 服务编排”,无需修改微服务业务代码,仅需添加配置文件;⑤ 建议提前备份本地微服务代码(避免实操中误改)。
一、先搞懂:容器化部署,解决微服务部署核心痛点
前九篇我们采用 “本地手动启动” 的方式运行微服务,这种方式在开发 / 测试 / 生产环境中都存在致命问题,核心痛点有 3 个:
- 部署步骤繁琐:启动一个完整的微服务集群需要依次启动 Nacos→Zipkin→ES→Kibana→Filebeat→user-service→order-service→gateway-service→SBA Server,共 9 个服务,手动操作耗时且易漏启动;
- 环境不一致:开发机、测试服务器、生产服务器的 JDK 版本、依赖库、配置路径可能不同,导致 “本地能跑、服务器报错”(经典的 “我本地没问题” 问题);
- 资源隔离差:所有服务运行在同一台机器的同一个 JVM / 进程中,一个服务占用过多资源会影响其他服务,且服务崩溃可能导致整个机器进程异常;
而 Docker+Compose 容器化部署正是解决这些痛点的最优方案:
- Docker:将每个服务(微服务 / Nacos/ES 等)打包成 “镜像”,镜像包含服务运行所需的所有环境(JDK、依赖、配置),实现 “一次打包、到处运行”,彻底解决环境不一致问题;
- Docker Compose:通过一个docker-compose.yml文件定义所有服务的启动规则(镜像、端口、依赖、网络、数据持久化),执行docker-compose up -d即可一键启动所有服务,无需逐个操作;
- 核心价值:环境一致化、部署一键化、资源隔离化,适配开发 / 测试 / 生产全环境的部署需求,是微服务落地的必经之路。
核心概念拆解(新手必记,避免混淆)
- Docker 核心概念:
- 镜像(Image):服务的 “安装包”,包含运行服务所需的代码、依赖、环境配置,只读不可修改;
- 容器(Container):镜像的运行实例,一个镜像可以启动多个容器,容器之间资源隔离;
- Dockerfile:构建镜像的 “脚本”,定义如何从基础镜像(如 JDK8)构建出当前服务的镜像;
- Docker Compose 核心概念:
- 服务(Service):一个服务对应一个容器(如 nacos 服务、order-service 服务);
- 网络(Network):Compose 会自动创建专属网络,所有服务在同一网络内可通过服务名互相访问(如 order-service 容器可通过nacos:8848访问 Nacos);
- 数据卷(Volume):实现容器内数据持久化(如 Nacos/ES 的数据存储到宿主机,容器删除后数据不丢失)。
补充:为什么选择 Docker+Compose 而非直接用 K8s?(新手必看)
K8s(Kubernetes)是生产级的容器编排工具,功能强大但配置复杂,适合大规模微服务集群(数十 / 数百个服务);
Docker Compose 轻量、配置简单,适合中小规模微服务集群(10 个以内服务),新手易上手,能快速实现 “一键部署”;
学习路径:先掌握 Docker+Compose(入门),再进阶学习 K8s(生产),符合新手循序渐进的学习逻辑。
二、实操核心:微服务容器化部署(Docker+Compose)
本篇实操分为三大模块、8 个核心步骤,从 “镜像构建” 到 “一键编排”,完整实现所有微服务的容器化部署:
模块一:环境准备(2 步)
① 验证 Docker 环境;
② 配置 Docker 国内镜像源(加速镜像下载);
模块二:构建微服务镜像(3 步)
① 给每个微服务编写 Dockerfile;
② 构建微服务镜像;
③ 验证镜像构建成功;
模块三:Compose 一键编排(3 步)
① 编写docker-compose.yml(定义所有服务);
② 一键启动所有服务;
③ 验证容器化部署效果;
重点说明:本次实操覆盖的服务包括:Nacos、Zipkin、ES、Kibana、Filebeat、user-service、order-service、gateway-service、SBA Server,共 9 个服务,全部通过 Compose 一键启动。
三、模块一:环境准备(核心前提)
3.1 第一步:验证 Docker 环境
- 打开终端(Windows:CMD/PowerShell,Mac/Linux:Terminal),执行以下命令验证 Docker 是否安装成功:
# 查看Docker版本
docker -v
# 查看Docker Compose版本
docker compose version
# 验证Docker服务是否运行
docker info
- 预期结果:命令无报错,显示 Docker/Compose 版本信息,说明环境正常;
(若报错 “Docker daemon is not running”,需启动 Docker Desktop 或 Docker 服务)
3.2 第二步:配置 Docker 国内镜像源(加速下载)
Docker 默认镜像源在国外,下载速度慢,配置国内镜像源(阿里云 / 网易):
- Windows/Mac:打开 Docker Desktop → Settings → Docker Engine → 在registry-mirrors中添加:
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://cr.console.aliyun.com/",
"https://docker.1ms.run",
"https://docker.xuanyuan.me"
]
}
-
Linux:编辑/etc/docker/daemon.json文件,添加上述镜像源,执行systemctl restart docker重启 Docker;
-
验证:执行docker info,在输出中能看到配置的镜像源,说明生效。
四、模块二:构建微服务镜像(核心,一次打包到处运行)
我们以order-service为例讲解 Dockerfile 编写和镜像构建,user-service、gateway-service、sba-server的配置几乎一致,仅需修改少量参数。
4.1 第一步:给微服务编写 Dockerfile
- 进入order-service项目根目录,新建文件Dockerfile(无后缀),内容如下:
# 基础镜像:JDK8(和Spring Boot 2.6.x兼容)
FROM openjdk:8-jdk-alpine
# 维护者信息(可选)
MAINTAINER xxx <your-email@xxx.com>
# 设置工作目录
WORKDIR /app
# 复制打包后的jar包到容器中(注意:需先打包微服务为jar包)
COPY target/order-service-0.0.1-SNAPSHOT.jar /app/order-service.jar
# 暴露端口(和微服务配置的端口一致)
EXPOSE 8082
# 启动命令(指定Nacos地址为容器名,后续Compose网络中可访问)
ENTRYPOINT ["java","-jar","/app/order-service.jar","--spring.cloud.nacos.discovery.server-addr=nacos:8848","--spring.cloud.nacos.config.server-addr=nacos:8848"]
关键说明:
- FROM openjdk:8-jdk-alpine:选择轻量的 Alpine 版本 JDK8,减少镜像体积;
- COPY:需先执行mvn clean package -DskipTests将微服务打包为 jar 包,放在target目录;
- ENTRYPOINT:启动命令中指定 Nacos 地址为nacos:8848(Compose 中 Nacos 服务名),而非localhost:8848(容器内localhost≠宿主机localhost);
- 暴露端口需和微服务配置的server.port一致(order-service 为 8082)。
- 给其他微服务编写 Dockerfile(仅修改标注部分):
- user-service:
FROM openjdk:8-jdk-alpine
MAINTAINER xxx <your-email@xxx.com>
WORKDIR /app
COPY target/user-service-0.0.1-SNAPSHOT.jar /app/user-service.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/app/user-service.jar","--spring.cloud.nacos.discovery.server-addr=nacos:8848","--spring.cloud.nacos.config.server-addr=nacos:8848"]
- gateway-service:
FROM openjdk:8-jdk-alpine
MAINTAINER xxx <your-email@xxx.com>
WORKDIR /app
COPY target/gateway-service-0.0.1-SNAPSHOT.jar /app/gateway-service.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app/gateway-service.jar","--spring.cloud.nacos.discovery.server-addr=nacos:8848","--spring.cloud.nacos.config.server-addr=nacos:8848"]
- sba-server:
FROM openjdk:8-jdk-alpine
MAINTAINER xxx <your-email@xxx.com>
WORKDIR /app
COPY target/sba-server-0.0.1-SNAPSHOT.jar /app/sba-server.jar
EXPOSE 8088
ENTRYPOINT ["java","-jar","/app/sba-server.jar","--spring.cloud.nacos.discovery.server-addr=nacos:8848"]
4.2 第二步:打包微服务并构建镜像
- 打包每个微服务:进入每个微服务根目录,执行 Maven 打包命令(需安装 Maven):
# 跳过测试打包,避免测试用例影响
mvn clean package -DskipTests
- 构建镜像:进入每个微服务根目录,执行docker build命令构建镜像:
# 构建order-service镜像,标签为springcloud/order-service:1.0
docker build -t springcloud/order-service:1.0 .
# 构建user-service镜像
docker build -t springcloud/user-service:1.0 .
# 构建gateway-service镜像
docker build -t springcloud/gateway-service:1.0 .
# 构建sba-server镜像
docker build -t springcloud/sba-server:1.0 .
说明:-t指定镜像标签(名称:版本),. 表示 Dockerfile 在当前目录。
4.3 第三步:验证镜像构建成功
执行以下命令查看已构建的镜像:
docker images
预期结果:列表中能看到springcloud/order-service:1.0、springcloud/user-service:1.0等镜像,说明构建成功。
五、模块三:Compose 一键编排(核心,一键启动所有服务)
我们编写docker-compose.yml文件,定义所有服务的启动规则,实现 “一键启动”。
5.1 第一步:编写 docker-compose.yml
在任意目录(建议新建springcloud-compose目录)新建docker-compose.yml文件,内容如下:
version: '3.8' # Compose版本,和Docker版本匹配
# 定义网络(所有服务在同一网络,可通过服务名访问)
networks:
springcloud-network:
driver: bridge
# 定义数据卷(持久化Nacos/ES数据)
volumes:
nacos-data:
es-data:
# 定义所有服务
services:
# 1. Nacos服务
nacos:
image: nacos/nacos-server:v2.0.7 # Nacos镜像版本和之前一致
container_name: nacos
ports:
- "8848:8848" # 端口映射:宿主机8848→容器8848
environment:
- MODE=standalone # 单机模式
- JVM_XMS=512m
- JVM_XMX=512m
volumes:
- nacos-data:/home/nacos/data # 数据持久化
networks:
- springcloud-network
restart: always # 容器异常退出时自动重启
# 2. Zipkin服务
zipkin:
image: openzipkin/zipkin:2.24 # Zipkin镜像
container_name: zipkin
ports:
- "9411:9411"
networks:
- springcloud-network
restart: always
# 3. Elasticsearch服务
elasticsearch:
image: elasticsearch:7.17.0 # ES版本和之前一致
container_name: elasticsearch
ports:
- "9200:9200"
- "9300:9300"
environment:
- discovery.type=single-node # 单机模式
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- xpack.security.enabled=false
volumes:
- es-data:/usr/share/elasticsearch/data
networks:
- springcloud-network
restart: always
# 4. Kibana服务(依赖ES)
kibana:
image: kibana:7.17.0
container_name: kibana
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200 # 访问ES的地址(服务名)
depends_on:
- elasticsearch # 依赖ES,ES启动后再启动Kibana
networks:
- springcloud-network
restart: always
# 5. Filebeat服务(依赖ES)
filebeat:
image: elastic/filebeat:7.17.0
container_name: filebeat
volumes:
# 挂载Filebeat配置文件(需提前编写filebeat.yml)
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml
# 挂载微服务日志目录(宿主机→容器)
- /var/lib/docker/volumes/springcloud-compose_order-service-logs/_data:/app/logs/order-service
- /var/lib/docker/volumes/springcloud-compose_user-service-logs/_data:/app/logs/user-service
- /var/lib/docker/volumes/springcloud-compose_gateway-service-logs/_data:/app/logs/gateway-service
depends_on:
- elasticsearch
networks:
- springcloud-network
restart: always
# 6. user-service服务(依赖Nacos)
user-service:
image: springcloud/user-service:1.0 # 本地构建的镜像
container_name: user-service
ports:
- "8081:8081"
volumes:
- user-service-logs:/app/logs # 日志持久化
depends_on:
- nacos
- zipkin
networks:
- springcloud-network
restart: always
# 7. order-service服务(依赖Nacos、user-service)
order-service:
image: springcloud/order-service:1.0
container_name: order-service
ports:
- "8082:8082"
volumes:
- order-service-logs:/app/logs
depends_on:
- nacos
- zipkin
- user-service
- elasticsearch
networks:
- springcloud-network
restart: always
# 8. gateway-service服务(依赖Nacos、order-service)
gateway-service:
image: springcloud/gateway-service:1.0
container_name: gateway-service
ports:
- "8080:8080"
volumes:
- gateway-service-logs:/app/logs
depends_on:
- nacos
- order-service
networks:
- springcloud-network
restart: always
# 9. SBA Server服务(依赖Nacos)
sba-server:
image: springcloud/sba-server:1.0
container_name: sba-server
ports:
- "8088:8088"
depends_on:
- nacos
- user-service
- order-service
networks:
- springcloud-network
restart: always
# 新增日志数据卷(微服务日志持久化)
volumes:
user-service-logs:
order-service-logs:
gateway-service-logs:
补充:Filebeat 配置文件(filebeat.yml)
在docker-compose.yml同级目录新建filebeat.yml,内容如下:
filebeat.inputs:
- type: log
enabled: true
paths:
- /app/logs/user-service/*.log
- /app/logs/order-service/*.log
- /app/logs/gateway-service/*.log
fields:
service: "springcloud-demo"
fields_under_root: true
output.elasticsearch:
hosts: ["elasticsearch:9200"]
index: "springcloud-log-%{+yyyy.MM.dd}"
setup.dashboards.enabled: false
setup.template.enabled: false
5.2 第二步:一键启动所有服务
- 进入docker-compose.yml所在目录,执行启动命令:
# 后台启动所有服务(-d:后台运行)
docker compose up -d
- 查看启动状态:
# 查看所有服务状态
docker compose ps
预期结果:所有服务的状态为Up,说明启动成功;若某服务状态为Exit,执行docker logs 容器名查看报错原因。
5.3 第三步:验证容器化部署效果
- 验证 Nacos:访问http://localhost:8848/nacos,能登录控制台,且服务列表中能看到user-service、order-service等服务;
- 验证接口访问:用 Postman 访问http://localhost:8080/gateway/order/create/1(携带 Token),能正常返回结果;
- 验证 ELK:访问http://localhost:5601,在 Kibana 中能看到微服务日志;
- 验证 SBA:访问http://localhost:8088,能看到所有微服务的监控状态;
- 验证数据持久化:停止容器(docker compose down)后重启,Nacos 配置、ES 日志数据不丢失。
六、实操总结与易错点复盘
本篇我们完成了微服务容器化部署的核心实操,实现了 “一次打包、一键部署”,核心收获如下:
- Docker 镜像构建核心:
- 核心流程:编写 Dockerfile → 打包微服务 jar 包 → 构建镜像 → 验证镜像;
- 关键知识点:基础镜像选择轻量版(Alpine)、容器内访问其他服务用 “服务名:端口”、暴露端口需和微服务一致;
- 核心价值:镜像包含完整运行环境,解决 “环境不一致” 问题;
- Compose 编排核心:
- 核心流程:编写 docker-compose.yml → 定义网络 / 数据卷 / 服务 → 一键启动 → 验证效果;
- 关键知识点:所有服务在同一网络可通过服务名访问、数据卷实现持久化、depends_on定义服务依赖顺序;
- 核心价值:一键启动所有服务,解决 “部署繁琐” 问题,提升部署效率;
新手必看易错点(重点避坑)
- 镜像构建失败:未执行mvn package打包 jar 包,或 Dockerfile 中COPY路径错误,需确保 jar 包在target目录;
- 容器内访问 Nacos 失败:启动命令中 Nacos 地址写localhost:8848(容器内localhost≠宿主机),需改为nacos:8848;
- ES 启动失败:内存配置不足,需在docker-compose.yml中设置ES_JAVA_OPTS=-Xms512m -Xmx512m;
- 服务依赖顺序错误:比如 gateway-service 先于 order-service 启动,导致网关无法注册,需通过depends_on定义依赖;
- 日志收集失败:Filebeat 挂载的日志目录路径错误,需确保宿主机日志目录正确映射到容器内;
- 端口冲突:宿主机端口被占用(如 8848 被本地 Nacos 占用),需关闭本地服务或修改 Compose 端口映射。
七、下一篇预告
本篇我们完成了微服务的容器化部署,解决了 “部署繁琐、环境不一致” 的核心痛点,让微服务集群具备了 “一键部署” 的能力。下一篇将讲解微服务进阶的核心痛点 ——分布式事务(Seata)实操,教大家解决 “跨服务数据一致性” 问题(比如下单扣库存时订单创建成功但库存扣减失败),实现微服务数据的最终一致性,筑牢生产环境的数据安全防线!
如果这篇实操教程对你有帮助,欢迎点赞、收藏、关注,实操过程中遇到任何问题(比如镜像构建失败、Compose 启动报错、容器间通信失败),都可以在评论区留言,我会逐一回复,帮大家解决新手踩坑问题~
更多推荐
所有评论(0)