Skip to content

Docker Compose 部署 Spring Boot 项目

Docker Compose 是部署 Spring Boot 项目的理想工具,它可以通过一个简单的 YAML 文件定义和运行多容器应用。下面我将详细介绍如何使用 Docker Compose 部署 Spring Boot 项目,包括基础配置、开发与生产环境优化以及常见问题解决方案。

1. 项目准备与基础配置

1.1 项目打包

首先确保你的 Spring Boot 项目已经正确打包成可执行的 JAR 文件。可以使用 Maven 命令:

bash
mvn clean package -DskipTests

这将在target目录下生成一个your-project-0.0.1-SNAPSHOT.jar文件。

1.2 创建 Dockerfile

在项目根目录创建Dockerfile,建议使用多阶段构建优化镜像大小:

dockerfile
# 构建阶段
FROM maven:3.8.6-jdk-11 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src /app/src
RUN mvn package -DskipTests

# 生产阶段
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
# 解决时区问题
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

这个 Dockerfile 使用了多阶段构建,第一阶段用 Maven 环境构建项目,第二阶段用轻量级的 JRE 运行环境。

2. Docker Compose 配置

2.1 基础 docker-compose.yml

在项目根目录创建docker-compose.yml文件:

yaml
version: "3.8"
services:
  app:
    build: .
    container_name: spring-boot-app
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - TZ=Asia/Shanghai
    restart: unless-stopped
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

这个配置定义了一个服务app,它会构建当前目录下的 Dockerfile,将容器的 8080 端口映射到主机的 8080 端口。

2.2 启动项目

运行以下命令构建并启动容器:

bash
docker-compose up --build -d

--build参数确保每次都会重新构建镜像,-d参数让容器在后台运行。

3. 高级配置选项

3.1 添加数据库服务

docker-compose.yml中添加 MySQL 数据库服务:

yaml
services:
  app:
    # ...原有配置
    depends_on:
      - db
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/mydb?useSSL=false&serverTimezone=Asia/Shanghai
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: root123

  db:
    image: mysql:8.0
    container_name: mysql-db
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: mydb
      TZ: Asia/Shanghai
    ports:
      - "3306:3306"
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - app-network

volumes:
  db-data:

这样 Spring Boot 应用可以通过服务名db访问 MySQL 数据库。

3.2 添加 Redis 缓存服务

yaml
services:
  app:
    # ...原有配置
    depends_on:
      - db
      - redis
    environment:
      SPRING_REDIS_HOST: redis
      SPRING_REDIS_PORT: 6379

  redis:
    image: redis:alpine
    container_name: redis-cache
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    networks:
      - app-network

volumes:
  redis-data:

3.3 开发环境配置

对于开发环境,可以配置热部署:

yaml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "8080:8080"
      - "5005:5005" # 远程调试端口
    volumes:
      - ./src:/app/src
    environment:
      - SPRING_PROFILES_ACTIVE=dev
      - SPRING_DEVTOOLS_RESTART_ENABLED=true

对应的Dockerfile.dev:

dockerfile
FROM maven:3.8.6-jdk-11
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src /app/src
CMD ["mvn", "spring-boot:run"]

4. 生产环境优化

4.1 使用更小的基础镜像

dockerfile
FROM eclipse-temurin:11-jre-alpine

4.2 添加健康检查

yaml
services:
  app:
    # ...其他配置
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3

4.3 资源限制

yaml
services:
  app:
    # ...其他配置
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 512M

5. 常见问题与解决方案

  1. 时区问题

    • 在 Dockerfile 中添加时区设置:RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  2. 数据库连接失败

    • 确保depends_on配置正确,并且应用有重连机制
    • 检查数据库 URL 中的服务名称是否与 docker-compose 中一致
  3. 端口冲突

    • 修改docker-compose.yml中的端口映射:"8081:8080"
  4. 构建速度慢

    • 使用.dockerignore文件排除不必要的文件
    • 分阶段复制文件,先复制pom.xml安装依赖

6. 完整生产环境示例

docker-compose.prod.yml:

yaml
version: "3.8"
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.prod
    image: my-spring-app:latest
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - SPRING_DATASOURCE_URL=jdbc:mysql://db:3306/mydb
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=root123
      - SPRING_REDIS_HOST=redis
    depends_on:
      - db
      - redis
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 512M

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: mydb
      TZ: Asia/Shanghai
    volumes:
      - db-data:/var/lib/mysql
    command: --default-authentication-plugin=mysql_native_password

  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data

volumes:
  db-data:
  redis-data:

Dockerfile.prod:

dockerfile
# 构建阶段
FROM maven:3.8.6-jdk-11 AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src /app/src
RUN mvn package -DskipTests

# 生产阶段
FROM eclipse-temurin:11-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

通过以上配置,你可以轻松地使用 Docker Compose 部署 Spring Boot 项目到生产环境。根据你的具体需求,可以调整配置中的参数和选项。