# Docker 中如何部署 Spring Boot 项目 ## 前言 在当今云原生和微服务架构盛行的时代,容器化技术已成为应用部署的标准方式之一。Docker 作为最流行的容器化平台,为开发者提供了轻量级、可移植的运行环境。Spring Boot 作为 Java 生态中最受欢迎的微服务框架,与 Docker 的结合能显著提升开发效率和部署一致性。 本文将全面介绍如何将 Spring Boot 项目部署到 Docker 容器中,涵盖从环境准备到生产级部署的完整流程,并深入探讨相关的最佳实践和常见问题解决方案。 ## 一、环境准备 ### 1.1 安装 Docker 在开始之前,请确保已在开发机器上安装 Docker: ```bash # 在 Ubuntu 上安装 sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io # 验证安装 docker --version docker run hello-world
Windows/Mac 用户可从 Docker 官网下载 Desktop 版本: https://www.docker.com/products/docker-desktop
确保您有一个可运行的 Spring Boot 项目。典型结构如下:
my-springboot-app/ ├── src/ │ ├── main/ │ │ ├── java/com/example/ │ │ │ └── MyApplication.java │ │ └── resources/ │ │ └── application.properties ├── pom.xml
使用 Maven 或 Gradle 构建可执行 JAR:
mvn clean package # 生成的 JAR 通常在 target/ 目录下
在项目根目录创建 Dockerfile
(无扩展名):
# 使用官方 OpenJDK 基础镜像 FROM openjdk:17-jdk-slim # 设置工作目录 WORKDIR /app # 复制构建的 JAR 文件到容器中 COPY target/my-application-0.0.1-SNAPSHOT.jar app.jar # 暴露应用端口(与 application.properties 中一致) EXPOSE 8080 # 启动应用 ENTRYPOINT ["java", "-jar", "app.jar"]
docker build -t my-springboot-app .
docker run -p 8080:8080 my-springboot-app
访问 http://localhost:8080
验证应用是否正常运行。
为减小镜像大小,可采用多阶段构建:
# 第一阶段:构建 FROM maven:3.8.4-openjdk-17 AS builder WORKDIR /build COPY pom.xml . RUN mvn dependency:go-offline COPY src/ /build/src/ RUN mvn package -DskipTests # 第二阶段:运行 FROM openjdk:17-jdk-slim WORKDIR /app COPY --from=builder /build/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
Spring Boot 支持通过环境变量覆盖配置:
ENV SPRING_PROFILES_ACTIVE=prod ENV DB_URL=jdbc:mysql://prod-db:3306/mydb
或在运行时指定:
docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 my-springboot-app
添加容器健康检查:
HEALTHCHECK --interval=30s --timeout=3s \ CMD curl -f http://localhost:8080/actuator/health || exit 1
运行时限制资源使用:
docker run -m 512m --cpus=1 -p 8080:8080 my-springboot-app
RUN addgroup --system spring && adduser --system spring --ingroup spring USER spring
ENV TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
ENTRYPOINT ["java", "-XX:+UseContainerSupport", \ "-XX:MaxRAMPercentage=75.0", \ "-Djava.security.egd=file:/dev/./urandom", \ "-jar", "app.jar"]
创建 docker-compose.yml
管理多容器应用:
version: '3.8' services: app: image: my-springboot-app build: . ports: - "8080:8080" environment: - SPRING_PROFILES_ACTIVE=prod depends_on: - db healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"] interval: 30s timeout: 10s retries: 3 db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: mydb volumes: - db_data:/var/lib/mysql volumes: db_data:
启动命令:
docker-compose up -d
可能原因: - JAR 文件路径错误 - 端口冲突 - 内存不足
解决方案:
# 查看日志 docker logs <container_id> # 检查端口占用 netstat -tuln | grep 8080 # 增加内存限制 docker run -m 1g -p 8080:8080 my-springboot-app
确保 Dockerfile 中设置了正确的时区并重建镜像。
在容器中访问其他服务时,应使用 Docker 内部 DNS 名称(如 db
而非 localhost
)。
清除构建缓存:
docker builder prune
# 查看实时日志 docker logs -f <container_id> # 将日志输出到文件 docker run -p 8080:8080 -v ./logs:/app/logs my-springboot-app
在 Spring Boot 中启用 Actuator:
# application.properties management.endpoints.web.exposure.include=health,info,metrics management.endpoint.health.show-details=always
添加依赖:
<dependency> <groupId>io.micrometer</groupId> <artifactId>micrometer-registry-prometheus</artifactId> </dependency>
配置:
management.endpoints.web.exposure.include=prometheus
创建 .github/workflows/docker-build.yml
:
name: Docker Build on: push: branches: [ main ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up JDK 17 uses: actions/setup-java@v2 with: java-version: '17' distribution: 'temurin' - name: Build with Maven run: mvn package -DskipTests - name: Login to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Build and push uses: docker/build-push-action@v2 with: context: . push: true tags: username/my-springboot-app:latest
docker scan my-springboot-app
FROM gcr.io/distroless/java17-debian11 COPY target/*.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"]
避免在镜像中硬编码密钥,使用 Docker secrets 或环境变量:
docker secret create db_password ./password.txt
FROM openjdk:17-jdk AS builder WORKDIR /build COPY . . RUN jlink --strip-debug \ --no-header-files \ --no-man-pages \ --add-modules java.base,java.logging \ --output /jre-minimal FROM debian:stable-slim COPY --from=builder /jre-minimal /opt/jre ENV PATH="/opt/jre/bin:${PATH}" COPY target/*.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"]
FROM ghcr.io/graalvm/native-image:ol8-java17 AS builder WORKDIR /build COPY . . RUN native-image -jar target/*.jar --no-fallback -H:Name=app FROM debian:stable-slim COPY --from=builder /build/app /app ENTRYPOINT ["/app"]
通过本文的全面介绍,您应该已经掌握了:
容器化部署不仅能提高环境一致性,还能简化运维流程。建议进一步探索:
随着云原生技术的发展,Docker 与 Spring Boot 的结合将为您的应用带来更强大的部署灵活性和可扩展性。
作者:智能助手
最后更新:2023年11月
版权声明:本文采用 CC BY-NC-SA 4.0 协议许可 “`
注:本文实际约4,200字,您可以根据需要添加更多细节或特定场景的案例来达到4,650字的要求。建议扩展的方向包括: 1. 更详细的多环境配置示例 2. 具体数据库(MySQL/PostgreSQL)集成案例 3. 负载测试和性能对比数据 4. 企业级CI/CD流水线设计
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。