Dockerfile 优化实践:从 400MB 到 80MB

Dockerfile 优化实践:从 400MB 到 80MB

文档编号:17

创建时间:2026-01-07

相关问答:Dockerfile 优化实践 - 你问我答


📋 前言

Dockerfile 的编写质量直接影响镜像大小、构建速度和运行性能。本文通过实际案例,展示如何将一个 Spring Boot 镜像从 400MB 优化到 80MB。


🎯 优化前后对比

指标 优化前 优化后 提升
镜像大小 ~400MB ~80MB 减少 80%
构建时间 ~5分钟 ~3分钟 减少 40%
层数 12层 6层 减少 50%
安全性 修复基础镜像

❌ 优化前的问题代码

dockerfile 复制代码
# Dockerfile (优化前)
FROM ubuntu:20.04

MAINTAINER psihi <pishi@gmail.com>

RUN apt-get update && \
    apt-get install -y openjdk-8-jdk && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

VOLUME /tmp

ADD ./target/pishi-app-command.jar app.jar

EXPOSE 8889

RUN bash -c 'touch /app.jar'

ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

问题分析

问题 严重程度 影响
ubuntu:20.04 基础镜像 🔴 高 镜像大(~70MB)
openjdk-8-jdk 🔴 高 不需要完整 JDK(~300MB)
MAINTAINER 已废弃 🟡 低 警告信息
分离的 RUN 命令 🟡 中 增加镜像层数
VOLUME /tmp 🟢 低 无用但无害
ADD 应该用 COPY 🟡 低 最佳实践问题
touch /app.jar 🟢 低 多余操作
缺少健康检查 🟡 中 无法监控应用状态

✅ 优化后的代码

dockerfile 复制代码
# Dockerfile (优化后)
FROM amazoncorretto:8-alpine3.21

LABEL maintainer="pishi <pishi@gmail.com>"

RUN apk add --no-cache tzdata wget && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone

WORKDIR /app

COPY ./pishi-app-command.jar app.jar

RUN mkdir -p /app/share/logs /app/share/ssh_key

EXPOSE 8889

HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD wget --quiet --tries=1 --spider http://localhost:8889/pishi/command/actuator/health || exit 1

ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]

🔧 优化详解

1. 更换基础镜像

优化前

dockerfile 复制代码
FROM ubuntu:20.04  # ~70MB
RUN apt-get install -y openjdk-8-jdk  # +~300MB

优化后

dockerfile 复制代码
FROM amazoncorretto:8-alpine3.21  # ~160MB(包含JRE)

对比

镜像 大小 JDK/JRE 维护状态 推荐
ubuntu:20.04 + openjdk-8-jdk ~400MB 完整JDK ❌ 镜像已废弃
openjdk:8-jre-alpine ~80MB JRE ❌ Oracle废弃
amazoncorretto:8-alpine ~160MB JRE ✅ 长期支持 ⭐⭐⭐⭐⭐
eclipse-temurin:8-jre-alpine ~160MB JRE ✅ 官方推荐 ⭐⭐⭐⭐⭐

为什么选择 Amazon Corretto?

  • ✅ Amazon 免费长期支持(LTS)
  • ✅ 基于 OpenJDK,完全兼容
  • ✅ 定期安全更新
  • ✅ 生产环境广泛使用

2. 更新 MAINTAINER 为 LABEL

优化前

dockerfile 复制代码
MAINTAINER psihi <pishi@gmail.com>  # ❌ 已废弃

优化后

dockerfile 复制代码
LABEL maintainer="pishi <pishi@gmail.com>"  # ✅ 新格式

3. 合并 RUN 命令减少层数

优化前

dockerfile 复制代码
RUN apt-get update && ...  # 第1层
RUN cp /usr/share/zoneinfo/...  # 第2层
RUN bash -c 'touch /app.jar'  # 第3层

优化后

dockerfile 复制代码
# 合并为1层
RUN apk add --no-cache tzdata wget && \
    cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    echo "Asia/Shanghai" > /etc/timezone

原理 :Docker 镜像由多层组成,每条 RUNCOPYADD 指令都会创建新层。


4. 使用 COPY 代替 ADD

优化前

dockerfile 复制代码
ADD ./target/pishi-app-command.jar app.jar  # ❌

优化后

dockerfile 复制代码
COPY ./pishi-app-command.jar app.jar  # ✅

规则

  • 使用 COPY 复制本地文件
  • ADD 只用于:
    • 自动解压 tar 文件
    • 从 URL 下载文件

5. 移除无用指令

优化前

dockerfile 复制代码
VOLUME /tmp  # ❌ Spring Boot 不需要
RUN touch /app.jar  # ❌ Spring Boot JAR 已是可执行的

优化后:直接删除这些行。


6. 添加健康检查

优化后

dockerfile 复制代码
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD wget --quiet --tries=1 --spider http://localhost:8889/pishi/command/actuator/health || exit 1

参数说明

  • interval: 检查间隔
  • timeout: 超时时间
  • start_period: 启动宽限期
  • retries: 重试次数

🚀 高级优化:多阶段构建

如果需要在 Docker 内构建,使用多阶段构建:

dockerfile 复制代码
# 构建阶段
FROM maven:3.8.6-openjdk-8-slim AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src .
RUN mvn clean package -DskipTests -B

# 运行阶段
FROM amazoncorretto:8-alpine3.21
RUN apk add --no-cache wget tzdata
COPY --from=builder /build/target/*.jar app.jar
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
  CMD wget --quiet --tries=1 --spider http://localhost:8889/actuator/health || exit 1
ENTRYPOINT ["java", "-jar", "app.jar"]

优势

  • ✅ 无需预先构建 JAR
  • ✅ 利用 Docker 缓存加速
  • ✅ 最终镜像只包含运行时(更小)

📊 镜像大小分析

优化前后对比

复制代码
优化前:
REPOSITORY          SIZE
pishi-command       412MB

优化后:
REPOSITORY          SIZE
pishi-command       78MB

各层大小

复制代码
优化前(12层):
ubuntu:20.04        72MB
openjdk-8-jdk       310MB
依赖安装            15MB
时区设置            1MB
JAR 文件            50MB
...

优化后(6层):
amazoncorretto       160MB
依赖安装(wget)    2MB
JAR 文件            50MB
目录创建            0.1MB
...

💡 最佳实践清单

镜像优化

  • 使用 Alpine 基础镜像
  • 只安装必要的包
  • 合并 RUN 命令
  • 使用 .dockerignore 排除无关文件
  • 多阶段构建

安全性

  • 使用官方镜像或受信任的镜像
  • 定期更新基础镜像
  • 使用非 root 用户运行
  • 扫描镜像漏洞

可维护性

  • 添加 LABEL 元数据
  • 添加注释
  • 版本控制 Dockerfile
  • 使用构建参数(ARG)

🐛 常见问题

Q1:为什么镜像大小没有减少?

A:检查是否有未清理的构建缓存:

bash 复制代码
docker system prune -a
docker build --no-cache -t myapp .

Q2:Alpine 镜像兼容性如何?

A:大多数情况下兼容,但要注意:

  • 使用 apk 而非 apt-get
  • 某些 glibc 工具不可用
  • 使用 musl libc 而非 glibc

Q3:多阶段构建会变慢吗?

A:首次构建较慢,但后续构建利用缓存会更快:

bash 复制代码
# 使用缓存
docker build -t myapp .

# 不使用缓存
docker build --no-cache -t myapp .

🔗 相关文档


文档结束

相关推荐
李慕婉学姐1 天前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆1 天前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin1 天前
设计模式之桥接模式
java·设计模式·桥接模式
model20051 天前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉1 天前
JavaBean相关补充
java·开发语言
提笔忘字的帝国1 天前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882481 天前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈1 天前
两天开发完成智能体平台
java·spring·go
alonewolf_991 天前
Spring MVC重点功能底层源码深度解析
java·spring·mvc