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 .

🔗 相关文档


文档结束

相关推荐
惊讶的猫6 小时前
探究StringBuilder和StringBuffer的线程安全问题
java·开发语言
jmxwzy6 小时前
Spring全家桶
java·spring·rpc
Halo_tjn6 小时前
基于封装的专项 知识点
java·前端·python·算法
Fleshy数模7 小时前
从数据获取到突破限制:Python爬虫进阶实战全攻略
java·开发语言
像少年啦飞驰点、7 小时前
零基础入门 Spring Boot:从“Hello World”到可上线的 Web 应用全闭环指南
java·spring boot·web开发·编程入门·后端开发
苍煜7 小时前
万字详解Maven打包策略:从基础插件到多模块实战
java·maven
有来技术7 小时前
Spring Boot 4 + Vue3 企业级多租户 SaaS:从共享 Schema 架构到商业化套餐设计
java·vue.js·spring boot·后端
东东5168 小时前
xxx医患档案管理系统
java·spring boot·vue·毕业设计·智慧城市
东东5168 小时前
学院个人信息管理系统 (springboot+vue)
vue.js·spring boot·后端·个人开发·毕设
一个响当当的名号8 小时前
lectrue9 索引并发控制
java·开发语言·数据库