Dockerfile使用指南

#docker #java #最佳实践

总结
  • 生产环境用多阶段构建,构建工具不进最终镜像;jar 已在 CI 构建好则用单阶段
  • 基础镜像选 eclipse-temurin:21-jre-alpine,运行 Spring Boot 只需 JRE
  • 容器内必须加 -XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0,否则 JVM 不感知容器内存限制

1. Java 应用标准 Dockerfile

生产环境推荐用多阶段构建,构建工具不进最终镜像,体积小、安全:

# 构建阶段
FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /app
# 先复制 pom.xml,利用缓存,依赖没变就不重新下载
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests

# 运行阶段
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

如果 jar 包已经在 CI 里构建好了,直接用单阶段:

FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

2. 常用 JVM 启动参数

容器环境下 JVM 默认不感知容器内存限制,需要显式配置:

ENTRYPOINT ["java", \
  "-XX:+UseContainerSupport", \
  "-XX:MaxRAMPercentage=75.0", \
  "-Djava.security.egd=file:/dev/./urandom", \
  "-jar", "app.jar"]

3. 基础镜像怎么选

java:8 这个镜像已经废弃,别用。现在主流选择:

镜像 大小 适用
eclipse-temurin:21-jre-alpine ~90MB 生产首选,体积小
eclipse-temurin:21-jre ~250MB 兼容性更好
amazoncorretto:21-alpine ~100MB AWS 环境
eclipse-temurin:21-jdk-alpine ~190MB 需要 JDK 工具时

运行 Spring Boot 只需要 JRE,不需要 JDK。

4. 几个关键指令

COPY vs ADD:优先用 COPYADD 只在需要自动解压 tar 包时用。

CMD vs ENTRYPOINT:Java 应用用 ENTRYPOINT 固定启动命令,CMD 可以作为默认参数被覆盖。

RUN 合并:多条命令合成一个 RUN,减少镜像层数:

RUN apt-get update && \
    apt-get install -y curl && \
    rm -rf /var/lib/apt/lists/*

WORKDIR:用 WORKDIR /app 设置工作目录,别用 RUN cd /app(不生效)。

5. .dockerignore

.git
target/
*.md
*.log
.env
.idea

target/ 排除掉,避免把本地编译产物带进构建上下文。

6. 常用构建命令

# 构建
docker build -t myapp:1.0 .

# 指定 Dockerfile
docker build -f Dockerfile.prod -t myapp:1.0 .

# 不用缓存(依赖有问题时用)
docker build --no-cache -t myapp:1.0 .