Spring Boot 项目 Docker 化:从零到一的完整实战指南
- [第一章:Docker 化价值与架构概述](#第一章:Docker 化价值与架构概述)
-
- [1.1 为什么需要 Docker 化 Spring Boot 应用?](#1.1 为什么需要 Docker 化 Spring Boot 应用?)
- [1.2 Spring Boot Docker 化架构全景图](#1.2 Spring Boot Docker 化架构全景图)
- 第二章:环境准备与基础工具链
-
- [2.1 Docker 环境安装配置](#2.1 Docker 环境安装配置)
- [2.2 项目结构与初始化](#2.2 项目结构与初始化)
- [第三章:Dockerfile 深度解析与实践](#第三章:Dockerfile 深度解析与实践)
-
- [3.1 基础 Dockerfile 编写](#3.1 基础 Dockerfile 编写)
- [3.2 多阶段构建优化](#3.2 多阶段构建优化)
- [3.3 高级特性与最佳实践](#3.3 高级特性与最佳实践)
- 第四章:构建优化与镜像管理
-
- [4.1 构建过程优化](#4.1 构建过程优化)
- [4.2 镜像标签与版本管理](#4.2 镜像标签与版本管理)
- 第五章:容器运行与调试
-
- [5.1 基础容器操作](#5.1 基础容器操作)
- [5.2 调试与故障排查](#5.2 调试与故障排查)
- [第六章:Docker Compose 编排实战](#第六章:Docker Compose 编排实战)
-
- [6.1 单服务编排](#6.1 单服务编排)
- [6.2 多服务编排(数据库+缓存+应用)](#6.2 多服务编排(数据库+缓存+应用))
- [6.3 环境特定配置](#6.3 环境特定配置)
- [第七章:Spring Boot 配置优化](#第七章:Spring Boot 配置优化)
-
- [7.1 容器感知配置](#7.1 容器感知配置)
- [7.2 健康检查与监控](#7.2 健康检查与监控)
- [第八章:CI/CD 集成实战](#第八章:CI/CD 集成实战)
-
- [8.1 GitHub Actions 集成](#8.1 GitHub Actions 集成)
- [8.2 Jenkins Pipeline 集成](#8.2 Jenkins Pipeline 集成)
- 第九章:生产环境最佳实践
-
- [9.1 安全加固](#9.1 安全加固)
- [9.2 性能优化](#9.2 性能优化)
- 第十章:故障排查与调试
-
- [10.1 常见问题解决](#10.1 常见问题解决)
- [10.2 调试工具集](#10.2 调试工具集)
- 第十一章:进阶主题与未来展望
-
- [11.1 Kubernetes 部署](#11.1 Kubernetes 部署)
- [11.2 服务网格集成](#11.2 服务网格集成)
- 总结
第一章:Docker 化价值与架构概述
1.1 为什么需要 Docker 化 Spring Boot 应用?
在微服务架构成为主流的今天,Docker 容器化技术为 Spring Boot 应用带来了革命性的优势:
环境一致性保障
- 消除「在我本地是好的」经典问题
- 确保开发、测试、生产环境完全一致
- 依赖项和系统库的版本锁定
持续集成/交付加速 - 构建一次,到处运行
- 简化部署流程,实现一键部署
- 与 Jenkins、GitLab CI 等工具天然集成
资源利用优化 - 轻量级容器 vs 传统虚拟机
- 快速启动和停止(秒级 vs 分钟级)
- 更高的部署密度和资源利用率
微服务架构支撑 - 每个服务独立容器化
- 简化服务发现和负载均衡
- 便于横向扩展和版本管理
1.2 Spring Boot Docker 化架构全景图
Spring Boot 应用代码 Dockerfile 构建配置 Docker Image 镜像 Docker Container 容器 容器编排平台 Maven/Gradle JAR/WAR 包 应用配置文件 Kubernetes Docker Swarm 云平台服务 监控日志 网络配置 数据卷
第二章:环境准备与基础工具链
2.1 Docker 环境安装配置
Linux 系统安装
bash
# Ubuntu/Debian 系统
sudo apt update
sudo apt install docker.io
sudo systemctl start docker
sudo systemctl enable docker
# 将当前用户加入 docker 组(避免每次 sudo)
sudo usermod -aG docker $USER
newgrp docker
# 验证安装
docker --version
docker run hello-world
Docker Desktop(Mac/Windows)
- 访问 Docker 官网下载安装包
- 启用 Kubernetes 集群(可选)
- 配置资源限制(内存/CPU)
2.2 项目结构与初始化
标准的 Spring Boot 项目结构
spring-boot-docker-demo/
├── src/
│ ├── main/
│ │ ├── java/com/example/demo/
│ │ │ ├── DemoApplication.java
│ │ │ ├── controller/
│ │ │ └── service/
│ │ └── resources/
│ │ ├── application.properties
│ │ └── application-docker.properties
├── pom.xml # 或 build.gradle
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
└── README.md
pom.xml 关键配置
xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
第三章:Dockerfile 深度解析与实践
3.1 基础 Dockerfile 编写
初版 Dockerfile(基础版)
dockerfile
# 使用官方 OpenJDK 运行时作为基础镜像
FROM openjdk:17-jdk-slim
# 设置工作目录
WORKDIR /app
# 复制构建好的 JAR 文件到容器中
COPY target/demo-0.0.1-SNAPSHOT.jar app.jar
# 暴露端口
EXPOSE 8080
# 设置 JVM 参数
ENV JAVA_OPTS="-Xmx512m -Xms256m"
# 运行应用程序
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
3.2 多阶段构建优化
优化版 Dockerfile(多阶段构建)
dockerfile
# 第一阶段:构建阶段
FROM maven:3.8.5-openjdk-17 AS builder
WORKDIR /build
# 复制 pom.xml 并下载依赖(利用 Docker 缓存)
COPY pom.xml .
RUN mvn dependency:go-offline
# 复制源码并构建
COPY src ./src
RUN mvn clean package -DskipTests
# 第二阶段:运行阶段
FROM openjdk:17-jdk-slim
WORKDIR /app
# 从构建阶段复制 JAR 文件
COPY --from=builder /build/target/demo-0.0.1-SNAPSHOT.jar app.jar
# 创建非 root 用户运行(安全最佳实践)
RUN groupadd -r spring && useradd -r -g spring spring
USER spring
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
3.3 高级特性与最佳实践
环境特定的 Dockerfile
dockerfile
# 开发环境配置
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/demo-0.0.1-SNAPSHOT.jar app.jar
# 开发环境 JVM 参数
ENV JAVA_OPTS="-Xmx512m -Xms256m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
EXPOSE 8080 5005
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
.dockerignore 文件配置
gitignore
# 忽略文件
.git
.gitignore
README.md
Dockerfile
docker-compose.yml
**/target/
**/.project
**/.classpath
**/.settings/
**/.idea/
**/*.iml
**/node_modules/
第四章:构建优化与镜像管理
4.1 构建过程优化
分层构建优化
dockerfile
FROM openjdk:17-jdk-slim
# 单独复制依赖项(利用缓存)
COPY target/dependency/BOOT-INF/lib /app/lib
COPY target/dependency/META-INF /app/META-INF
COPY target/dependency/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.demo.DemoApplication"]
Maven 分层配置
xml
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>
4.2 镜像标签与版本管理
自动化构建脚本
bash
#!/bin/bash
# build.sh
APP_NAME="spring-boot-demo"
VERSION="1.0.0"
TIMESTAMP=$(date +%Y%m%d%H%M%S)
# 构建镜像
echo "构建 Docker 镜像..."
docker build -t ${APP_NAME}:${VERSION} .
docker build -t ${APP_NAME}:latest .
# 添加时间戳标签
docker tag ${APP_NAME}:latest ${APP_NAME}:${VERSION}-${TIMESTAMP}
# 推送到镜像仓库(可选)
# docker tag ${APP_NAME}:latest your-registry/${APP_NAME}:latest
# docker push your-registry/${APP_NAME}:latest
echo "镜像构建完成:"
docker images | grep ${APP_NAME}
第五章:容器运行与调试
5.1 基础容器操作
运行容器
bash
# 基础运行
docker run -p 8080:8080 spring-boot-demo:latest
# 后台运行
docker run -d --name myapp -p 8080:8080 spring-boot-demo:latest
# 带环境变量
docker run -d \
--name myapp \
-p 8080:8080 \
-e "SPRING_PROFILES_ACTIVE=docker" \
-e "DATABASE_URL=jdbc:mysql://db:3306/mydb" \
spring-boot-demo:latest
容器管理命令
bash
# 查看运行中的容器
docker ps
# 查看所有容器
docker ps -a
# 查看容器日志
docker logs myapp
docker logs -f myapp # 实时日志
# 进入容器
docker exec -it myapp /bin/bash
# 停止和删除容器
docker stop myapp
docker rm myapp
# 查看容器资源使用
docker stats myapp
5.2 调试与故障排查
远程调试配置
bash
# 运行支持远程调试的容器
docker run -d \
--name myapp-debug \
-p 8080:8080 \
-p 5005:5005 \
-e "JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005" \
spring-boot-demo:latest
健康检查验证
bash
# 检查容器健康状态
docker inspect --format='{{.State.Health.Status}}' myapp
# 手动健康检查
curl http://localhost:8080/actuator/health
第六章:Docker Compose 编排实战
6.1 单服务编排
基础 docker-compose.yml
yaml
version: '3.8'
services:
app:
image: spring-boot-demo:latest
container_name: spring-boot-app
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- JAVA_OPTS=-Xmx512m -Xms256m
networks:
- app-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
app-network:
driver: bridge
6.2 多服务编排(数据库+缓存+应用)
完整的微服务栈
yaml
version: '3.8'
services:
# MySQL 数据库
mysql:
image: mysql:8.0
container_name: mysql-db
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: myapp
MYSQL_USER: appuser
MYSQL_PASSWORD: apppassword
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./config/mysql.cnf:/etc/mysql/conf.d/custom.cnf
networks:
- app-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 10s
retries: 5
# Redis 缓存
redis:
image: redis:6.2-alpine
container_name: redis-cache
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- app-network
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
# Spring Boot 应用
app:
build:
context: .
dockerfile: Dockerfile
container_name: spring-boot-app
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/myapp
- SPRING_DATASOURCE_USERNAME=appuser
- SPRING_DATASOURCE_PASSWORD=apppassword
- SPRING_REDIS_HOST=redis
- SPRING_REDIS_PORT=6379
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_healthy
networks:
- app-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
volumes:
mysql_data:
redis_data:
networks:
app-network:
driver: bridge
6.3 环境特定配置
docker-compose.override.yml(开发环境)
yaml
version: '3.8'
services:
app:
ports:
- "8080:8080"
- "5005:5005" # 调试端口
environment:
- JAVA_OPTS=-Xmx512m -Xms256m -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
volumes:
- ./src:/app/src:ro # 源码热加载
- ./logs:/app/logs
docker-compose.prod.yml(生产环境)
yaml
version: '3.8'
services:
app:
environment:
- JAVA_OPTS=-Xmx1g -Xms512m -XX:+UseG1GC
deploy:
resources:
limits:
memory: 1g
cpus: '2'
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
第七章:Spring Boot 配置优化
7.1 容器感知配置
application-docker.properties
properties
# 容器特定配置
server.port=8080
management.server.port=8081
management.endpoints.web.exposure.include=health,info,metrics
# 健康检查配置
management.endpoint.health.show-details=always
management.endpoint.health.probes.enabled=true
# 日志配置
logging.level.com.example=INFO
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n
logging.file.name=/app/logs/application.log
# 性能优化
server.tomcat.threads.max=200
server.tomcat.threads.min-spare=20
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
Docker 环境检测
java
@Configuration
public class DockerConfig {
@Bean
@ConditionalOnProperty(name = "docker.enabled", havingValue = "true")
public DockerEnvironment dockerEnvironment() {
return new DockerEnvironment();
}
@Bean
@ConditionalOnExpression("'${spring.profiles.active}'.contains('docker')")
public ProfileSpecificConfig profileConfig() {
return new ProfileSpecificConfig();
}
}
7.2 健康检查与监控
自定义健康检查
java
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Autowired
private DataSource dataSource;
@Override
public Health health() {
try {
// 检查数据库连接
if (dataSource.getConnection().isValid(1000)) {
return Health.up()
.withDetail("database", "available")
.build();
}
} catch (SQLException e) {
return Health.down(e)
.withDetail("database", "unavailable")
.build();
}
return Health.unknown().build();
}
}
第八章:CI/CD 集成实战
8.1 GitHub Actions 集成
.github/workflows/docker-build.yml
yaml
name: Docker Build and Push
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: Build with Maven
run: mvn clean package -DskipTests
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
yourusername/spring-boot-demo:latest
yourusername/spring-boot-demo:${{ github.sha }}
8.2 Jenkins Pipeline 集成
Jenkinsfile
groovy
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'your-registry.com'
IMAGE_NAME = 'spring-boot-demo'
}
stages {
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
}
stage('Build Docker Image') {
steps {
script {
docker.build("${IMAGE_NAME}:${env.BUILD_ID}")
}
}
}
stage('Push Docker Image') {
steps {
script {
docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-credentials') {
docker.image("${IMAGE_NAME}:${env.BUILD_ID}").push()
}
}
}
}
stage('Deploy to Staging') {
steps {
sh '''
docker-compose -f docker-compose.staging.yml down
docker-compose -f docker-compose.staging.yml up -d
'''
}
}
}
post {
always {
cleanWs()
}
}
}
第九章:生产环境最佳实践
9.1 安全加固
非 root 用户运行
dockerfile
FROM openjdk:17-jdk-slim
RUN groupadd -r spring && useradd -r -g spring spring
USER spring
WORKDIR /app
COPY --chown=spring:spring target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
安全扫描
bash
# 使用 Trivy 扫描镜像漏洞
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image spring-boot-demo:latest
# 使用 Docker Scout
docker scout quickview spring-boot-demo:latest
9.2 性能优化
JVM 调优
dockerfile
FROM openjdk:17-jdk-slim
ENV JAVA_OPTS="-Xmx1g -Xms1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+UseContainerSupport"
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.jar"]
资源限制
yaml
# docker-compose.prod.yml
services:
app:
deploy:
resources:
limits:
memory: 2g
cpus: '2'
reservations:
memory: 1g
cpus: '0.5'
第十章:故障排查与调试
10.1 常见问题解决
内存问题排查
bash
# 查看容器内存使用
docker stats myapp
# 进入容器查看进程
docker exec -it myapp ps aux
# JVM 内存分析
docker exec -it myapp jcmd 1 GC.heap_info
日志分析
bash
# 实时查看日志
docker logs -f myapp
# 查看特定时间段的日志
docker logs --since 1h myapp
# 日志导出分析
docker logs myapp > app.log
10.2 调试工具集
诊断脚本
bash
#!/bin/bash
# diagnose.sh
CONTAINER_NAME="spring-boot-app"
echo "=== 容器状态 ==="
docker ps -a | grep $CONTAINER_NAME
echo "=== 资源使用 ==="
docker stats $CONTAINER_NAME --no-stream
echo "=== 最近日志 ==="
docker logs --tail 50 $CONTAINER_NAME
echo "=== 健康状态 ==="
docker inspect --format='{{.State.Health.Status}}' $CONTAINER_NAME
echo "=== 网络检查 ==="
docker exec $CONTAINER_NAME curl -s http://localhost:8080/actuator/health
第十一章:进阶主题与未来展望
11.1 Kubernetes 部署
基础的 Deployment 配置
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-boot-app
spec:
replicas: 3
selector:
matchLabels:
app: spring-boot-app
template:
metadata:
labels:
app: spring-boot-app
spec:
containers:
- name: app
image: your-registry/spring-boot-demo:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "kubernetes"
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
11.2 服务网格集成
Istio 边车配置
yaml
apiVersion: v1
kind: Service
metadata:
name: spring-boot-app
labels:
app: spring-boot-app
spec:
ports:
- port: 8080
name: http
selector:
app: spring-boot-app
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: spring-boot-app
spec:
host: spring-boot-app
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
总结
通过本指南,你已经掌握了 Spring Boot 项目 Docker 化的完整流程。从基础的 Dockerfile 编写到生产环境的最佳实践,这些知识将帮助你构建可维护、可扩展的容器化应用。
关键要点回顾:
- 多阶段构建显著减小镜像大小
- 健康检查确保应用可靠性
- Docker Compose简化多服务编排
- CI/CD 集成实现自动化部署
- 安全配置保护生产环境
随着云原生技术的发展,容器化已成为现代应用开发的标配。掌握这些技能将为你的职业发展和项目成功奠定坚实基础。