Spring Boot 项目 Docker 化:从零到一的完整实战指南

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 编写到生产环境的最佳实践,这些知识将帮助你构建可维护、可扩展的容器化应用。

关键要点回顾:

  1. 多阶段构建显著减小镜像大小
  2. 健康检查确保应用可靠性
  3. Docker Compose简化多服务编排
  4. CI/CD 集成实现自动化部署
  5. 安全配置保护生产环境
    随着云原生技术的发展,容器化已成为现代应用开发的标配。掌握这些技能将为你的职业发展和项目成功奠定坚实基础。
相关推荐
zl9798993 小时前
MySQL-数据库日志
数据库·mysql·database
JarvanMo3 小时前
我尝试了Appwrite, Supabase和 Firebase Databases
前端·后端
阿里嘎多哈基米3 小时前
Mac系统,Docker的MySQL + 本地 Canal
mysql·macos·docker·canal
老葱头蒸鸡3 小时前
(8)ASP.NET Core2.2 中的MVC路由一
后端·asp.net·mvc
LoneEon3 小时前
Ubuntu 部署 Harbor 构建企业级私有镜像仓库
linux·运维·ubuntu·docker·harbor
uhakadotcom3 小时前
分享近期学到的postgresql的几个实用的新特性!
后端·面试·github
刘立军3 小时前
本地大模型编程实战(37)使用知识图谱增强RAG(3)
后端·架构·llm