【Docker实战】Spring Boot应用容器化
Docker实战:Spring Boot应用容器化
以"Spring Boot + MySQL"为例,详细讲解容器化部署的关键步骤,重点关注多阶段构建、环境配置与网络通信等核心要点。适用于企业级应用部署参考。
1. 项目结构
springboot-demo/
├── Dockerfile # 多阶段构建脚本(定义镜像构建流程,包含编译和运行阶段)
├── pom.xml # Maven依赖配置(管理Java项目第三方库及版本)
├── src/ # 业务代码(包含Controller、Service、Entity等核心逻辑)
├── application.yml # 应用配置(基础参数设置,支持通过环境变量动态覆盖)
└── entrypoint.sh # 启动脚本(检查MySQL依赖就绪状态并注入环境变量)
2. 多阶段Dockerfile构建
# 阶段1:代码编译(使用maven镜像编译代码并提取分层依赖)
FROM maven:3.8.6-openjdk-11 AS builder
WORKDIR /app# 缓存依赖(当pom.xml不变时复用缓存,避免重复下载)
COPY pom.xml .
RUN mvn dependency:go-offline# 复制源代码并编译打包
COPY src ./src
RUN mvn package -DskipTests && \# 提取Spring Boot分层文件(优化镜像层缓存,仅更新变动层)java -Djarmode=layertools -jar target/*.jar extract# 阶段2:运行环境(仅包含运行时必需组件,大幅减小镜像体积)
FROM openjdk:11-jre-slim
WORKDIR /app# 按变更频率排序复制分层文件,优化缓存利用率
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./# 配置启动脚本
COPY entrypoint.sh .
RUN chmod +x entrypoint.sh# 声明应用端口
EXPOSE 8080# 容器启动入口
ENTRYPOINT ["./entrypoint.sh"]
3. 启动脚本(依赖检查)
#!/bin/bash
set -e # 脚本执行出错时立即退出# 等待MySQL服务就绪(避免应用启动时数据库未初始化完成)
echo "等待MySQL服务: $MYSQL_HOST:$MYSQL_PORT"
while ! nc -z $MYSQL_HOST $MYSQL_PORT; dosleep 1 # 每1秒检查一次连接
done
echo "MySQL服务已就绪,启动应用..."# 启动Spring Boot应用(通过环境变量注入数据库配置)
exec java org.springframework.boot.loader.JarLauncher \--spring.datasource.url=jdbc:mysql://$MYSQL_HOST:$MYSQL_PORT/$MYSQL_DATABASE?useSSL=false&serverTimezone=UTC \--spring.datasource.username=$MYSQL_USER \--spring.datasource.password=$MYSQL_PASSWORD
4. 应用配置(环境变量覆盖)
server:port: 8080 # 应用监听端口spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driver# 数据库默认配置(可被环境变量覆盖)url: jdbc:mysql://localhost:3306/defaultdb?useSSL=false&serverTimezone=UTCusername: rootpassword: passwordjpa:hibernate:ddl-auto: update # 开发环境自动创建表结构(生产环境建议改为none)show-sql: true # 打印执行的SQL语句(开发环境使用)
5. 部署流程
# 1. 构建镜像
docker build -t springboot-demo:v1 .# 2. 启动MySQL容器(带数据持久化和字符集配置)
docker run -d --name mysql \-v mysql-data:/var/lib/mysql \ # 数据卷持久化-e MYSQL_DATABASE=appdb \ # 初始化应用数据库-e MYSQL_ROOT_PASSWORD=123456 \ # 数据库密码mysql:8.0 \--character-set-server=utf8mb4 \ # 支持特殊字符--collation-server=utf8mb4_unicode_ci# 3. 创建自定义网络
docker network create app-net
docker network connect app-net mysql # 将MySQL加入网络# 4. 启动Spring Boot应用
docker run -d --name springboot-app \--network app-net \ # 加入自定义网络-p 8080:8080 \ # 端口映射-e MYSQL_HOST=mysql \ # 数据库配置-e MYSQL_PORT=3306 \-e MYSQL_DATABASE=appdb \-e MYSQL_USER=root \-e MYSQL_PASSWORD=123456 \springboot-demo:v1# 5. 验证启动
curl http://localhost:8080/health
# 输出示例:{"status":"UP","components":{"db":{"status":"UP","details":{"database":"MySQL","version":"8.0.28"}}}}
6. 问题排查指南
-
数据库连接问题:
# 检查网络连通性 docker exec -ti springboot-app ping mysql# 查看应用日志 docker logs -f springboot-app | grep -i "could not connect to database"
-
镜像优化:
- 运行
docker history springboot-demo:v1
检查镜像层 - 基础镜像对比:
openjdk:11-jre-slim
:约80MBopenjdk:11-jre-alpine
:约50MB(注意musl-libc兼容性)
- 运行
-
容器调试:
docker exec -ti springboot-app /bin/bash # 执行网络诊断命令
最佳实践
-
使用Docker Compose管理多容器:
version: '3' services:mysql:image: mysql:8.0environment:MYSQL_ROOT_PASSWORD: 123456MYSQL_DATABASE: appdbvolumes:- mysql-data:/var/lib/mysqlapp:image: springboot-demo:v1ports:- "8080:8080"environment:MYSQL_HOST: mysqldepends_on:- mysqlvolumes:mysql-data:
-
生产环境建议:
- 敏感配置使用Docker Secrets或配置中心管理
- 镜像标签关联Git Commit ID(如
springboot-demo:abc123
) - 配置健康检查(
HEALTHCHECK
指令)