容器化部署:服务镜像与 docker compose 编排要点
微服务最终要跑在容器里,才能获得一致的运行环境与可复制的部署。Spring Boot 应用容器化很简单,但“能跑”和“生产可跑”之间有不少要点:镜像怎么建、Compose 怎么编排、健康检查怎么做。
构建服务镜像
Spring Boot 应用构建镜像,最省事的是把可执行 jar 放进 JRE 镜像。注意不要用体积巨大的 JDK 全量镜像,基础镜像尽量小。
# Dockerfile(示例:Java 17 + Boot 3)
FROM eclipse-temurin:17-jre
WORKDIR /app
# 利用 Spring Boot 分层 jar,先拷依赖层再拷业务层,提高构建缓存命中
COPY target/order-service-1.0.0.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]
要点:
- 通过
spring-boot-maven-plugin生成分层(layered)jar 后,可用COPY --from只复制需要的层,实现“依赖没变就不重新拉层”的加速。 - 设置 JVM 内存比例参数(
-XX:MaxRAMPercentage)让容器内的 JVM 感知容器配额,避免 OOM 与资源浪费。 - 每个服务一个镜像仓库地址 + 版本标签,如
registry.example.com/order-service:20250601-1,标签唯一且可追溯源码提交。
# 构建与推送示意(示例仓库地址)
docker build -t registry.example.com/order-service:1.0.0 ./order-service
docker push registry.example.com/order-service:1.0.0
docker compose 编排
本地开发或小规模部署时,用 compose 一键拉起整套环境:注册中心、数据库、Redis 与各服务。
services:
nacos:
image: nacos/nacos-server:v2.3.2 # 教程锚点 Nacos 3.x,2.x 亦可运行,tag 以官方为准
ports: ["8848:8848", "9848:9848"]
environment:
MODE: standalone
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8848/nacos/v1/console/health/readiness"]
interval: 10s
retries: 10
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: example
volumes: ["mysql-data:/var/lib/mysql"]
order-service:
build: ./order-service
depends_on:
nacos: { condition: service_healthy }
mysql: { condition: service_started }
environment:
SPRING_PROFILES_ACTIVE: docker
SPRING_CLOUD_NACOS_SERVER_ADDR: nacos:8848
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/order_db?useSSL=false
ports: ["8081:8080"]
volumes:
mysql-data:
编排要点:
- 容器间用服务名互访(
nacos:8848),不写死 IP;应用配置通过环境变量注入,配置文件里不留明文口令。 depends_on只保证启动顺序,不代表依赖“就绪”,配合 healthcheck 的condition: service_healthy才可靠。- 配置差异用 profile 或环境变量区分(本地/测试/生产),镜像本身不区分环境。
- 日志统一输出到 stdout,交给 docker 日志驱动或采集器,不要写容器内文件。
镜像瘦身与安全
- 优先官方维护的基础镜像并固定版本 tag;定期升级修补 CVE。
- 容器内以非 root 用户运行(如
USER app),减小被攻破后的影响面。 - 不需要的构建产物(源码、.m2 缓存)不进镜像,用
.dockerignore排除target/、.git/。 - 同时给每个服务配资源限额(compose 的
deploy.resources.limits或 k8s 的 requests/limits),防止单个服务吃光宿主机。
从 compose 走向编排平台
compose 适合单机与小规模验证;当需要多副本、自动伸缩、滚动发布时,就迁移到 Kubernetes 等编排平台(见 Kubernetes 章节)。迁移时保持“镜像与运行环境解耦、配置外置、无状态化”这三条原则,容器化阶段的投入才不会白费。
小结
容器化的关键是产出一致的镜像与声明式的编排:Dockerfile 负责把应用和环境打包,compose 负责把多服务拓扑管起来,环境变量负责把配置差异隔离出去。先在本机用 compose 跑通整套调用链,再谈上编排平台。