Docker 容器化部署 Spring Boot 应用的完整实践
Docker 容器化部署 Spring Boot 应用的完整实践
前言
在当今云原生时代,容器化技术已经成为应用部署的标准方式之一。Docker 作为最流行的容器化平台,为开发者提供了轻量级、可移植的运行环境。本文将详细介绍如何使用 Docker 容器化部署 Spring Boot 应用,涵盖从项目准备到生产环境部署的完整流程。
一、准备工作
1.1 环境要求
在开始之前,请确保你的开发环境满足以下要求:
- JDK 8 或更高版本(推荐 JDK 17)
- Maven 3.6+ 或 Gradle 7.x 构建工具
- Docker 环境(Docker Desktop 或 Docker Engine 20.10+)
- 一个简单的 Spring Boot 2.7+ 应用(如果没有,可以使用 Spring Initializr 创建示例应用)
1.2 Spring Boot 应用准备
确保你的 Spring Boot 应用能够正常构建和运行。一个典型的 Spring Boot 项目结构如下:
spring-boot-docker-demo/
├── src/
│ ├── main/
│ │ ├── java/ # 应用源代码
│ │ └── resources/ # 配置文件
│ └── test/ # 测试代码
├── pom.xml # Maven 配置文件
├── Dockerfile # Docker 构建文件
└── .dockerignore # Docker 忽略文件
二、创建 Dockerfile
Dockerfile 是构建 Docker 镜像的蓝图。在项目根目录下创建一个名为 Dockerfile 的文件(无扩展名),内容如下:
# 第一阶段:构建应用
FROM openjdk:17-jdk-slim as builder
# 设置工作目录
WORKDIR /app
# 复制构建文件和源代码
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
COPY src src
# 构建应用(跳过测试以加快构建速度)
RUN ./mvnw clean package -DskipTests
# 第二阶段:运行应用
FROM openjdk:17-jre-slim
# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 创建非root用户运行应用
RUN groupadd -r spring && useradd -r -g spring spring
USER spring
# 设置工作目录
WORKDIR /app
# 从构建阶段复制生成的 jar 文件
COPY --from=builder /app/target/*.jar app.jar
# 暴露应用端口
EXPOSE 8080
# 设置JVM参数(可根据需要调整)
ENV JAVA_OPTS="-Xms256m -Xmx512m -XX:+UseG1GC"
# 设置启动命令
ENTRYPOINT exec java ${JAVA_OPTS} -jar app.jar
这个 Dockerfile 使用了多阶段构建,可以显著减小最终镜像的大小,并遵循了安全最佳实践。
三、构建 Docker 镜像
在包含 Dockerfile 的目录下,运行以下命令构建镜像:
docker build -t spring-boot-app:1.0.0 .
参数说明:
-t:指定镜像名称和标签(格式:name:tag)1.0.0:建议使用语义化版本号.:表示当前目录是构建上下文
四、运行 Docker 容器
构建完成后,可以使用以下命令运行容器:
docker run -d --name my-spring-app \
-p 8080:8080 \
-e "SPRING_PROFILES_ACTIVE=prod" \
--memory=512m \
--cpus=1 \
spring-boot-app:1.0.0
参数说明:
-d:后台运行容器--name:指定容器名称-p 8080:8080:端口映射(主机端口:容器端口)-e:设置环境变量--memory:限制内存使用--cpus:限制CPU使用
五、优化 Docker 镜像
5.1 使用 .dockerignore 文件
在项目根目录创建 .dockerignore 文件,排除不必要的文件:
.git
.gitignore
target
*.iml
.idea
*.md
*.log
.DS_Store
/docker
/bin
5.2 使用 Alpine 基础镜像
为了进一步减小镜像大小,可以使用 Alpine Linux 基础镜像:
FROM openjdk:17-jdk-alpine as builder
...
FROM openjdk:17-jre-alpine
...
5.3 分层构建优化
优化 Dockerfile 以提高构建缓存利用率:
# 只复制POM文件先下载依赖(利用Docker缓存层)
COPY pom.xml .
RUN ./mvnw dependency:go-offline
# 然后复制源代码
COPY src src
六、使用 Docker Compose 管理服务
对于需要多个服务的应用(如需要数据库),可以使用 Docker Compose。创建 docker-compose.yml 文件:
version: '3.8'
services:
app:
image: spring-boot-app:1.0.0
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mydb
- SPRING_DATASOURCE_USERNAME=postgres
- SPRING_DATASOURCE_PASSWORD=example
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
db:
image: postgres:13-alpine
environment:
POSTGRES_PASSWORD: example
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
volumes:
postgres_data:
启动服务:
docker-compose up -d --build
七、生产环境部署建议
7.1 安全最佳实践
- 使用非root用户运行容器
- 定期更新基础镜像以获取安全补丁
- 扫描镜像中的漏洞:
docker scan spring-boot-app:1.0.0
7.2 日志管理
配置日志驱动和日志轮转:
docker run -d \
--log-driver=json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
spring-boot-app:1.0.0
7.3 监控和指标
集成Spring Boot Actuator和Prometheus监控:
# 暴露监控端点
EXPOSE 8080 9090
# docker-compose.yml 中添加
monitoring:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
八、持续集成/持续部署 (CI/CD)
可以将 Docker 构建集成到 CI/CD 流程中。以下是一个完整的 GitHub Actions 示例:
name: Build, Test and Deploy
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
env:
IMAGE_NAME: spring-boot-app
LATEST_TAG: latest
VERSION_TAG: ${{ github.sha }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- 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 -B verify --file pom.xml
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v3
with:
context: .
push: ${{ github.event_name == 'push' }}
tags: |
${{ secrets.DOCKER_HUB_USERNAME }}/$IMAGE_NAME:$VERSION_TAG
${{ secrets.DOCKER_HUB_USERNAME }}/$IMAGE_NAME:$LATEST_TAG
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Deploy to Production
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
ssh ${{ secrets.SSH_HOST }} "docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/$IMAGE_NAME:$VERSION_TAG"
ssh ${{ secrets.SSH_HOST }} "docker-compose -f /path/to/docker-compose.yml up -d"
结语
通过本文的介绍,你应该已经掌握了使用 Docker 容器化部署 Spring Boot 应用的完整流程。从基础的 Dockerfile 编写到生产环境的最佳实践,容器化技术为 Spring Boot 应用提供了更加灵活、高效的部署方式。在实际项目中,可以根据具体需求进一步优化和调整这些配置,并结合 Kubernetes 等编排工具实现更强大的部署方案。
- -
更多推荐
所有评论(0)