【Docker实战】Spring Boot应用容器化

发布于:2025-08-11 ⋅ 阅读:(13) ⋅ 点赞:(0)

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; do
  sleep 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=UTC
    username: root
    password: password
  jpa:
    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:约80MB
      • openjdk:11-jre-alpine:约50MB(注意musl-libc兼容性)
  • 容器调试

    docker exec -ti springboot-app /bin/bash
    # 执行网络诊断命令
    

最佳实践

  1. 使用Docker Compose管理多容器

    version: '3'
    services:
      mysql:
        image: mysql:8.0
        environment:
          MYSQL_ROOT_PASSWORD: 123456
          MYSQL_DATABASE: appdb
        volumes:
          - mysql-data:/var/lib/mysql
      
      app:
        image: springboot-demo:v1
        ports:
          - "8080:8080"
        environment:
          MYSQL_HOST: mysql
        depends_on:
          - mysql
    
    volumes:
      mysql-data:
    
  2. 生产环境建议:

    • 敏感配置使用Docker Secrets或配置中心管理
    • 镜像标签关联Git Commit ID(如springboot-demo:abc123
    • 配置健康检查(HEALTHCHECK指令)

网站公告

今日签到

点亮在社区的每一天
去签到