镜像和容器的核心区别在于:镜像是只读的分层模板,用于创建容器;容器是其运行实例,拥有独立隔离环境及可写顶层。
镜像和容器是 docker 的两个核心概念:镜像(image)是只读的、分层的模板,用来创建容器;容器(container)是镜像的运行实例,拥有可写顶层。镜像体积过大,本质不是容器运行时的问题,而是构建过程中把不该留下的东西固化进了镜像层里——比如编译器、缓存、文档、调试工具、甚至整个操作系统。
选对基础镜像,直接砍掉一半体积
基础镜像常占最终体积的 50% 以上。用 ubuntu:22.04(约 70MB) 跑一个 Python 脚本,就像派辆卡车送一张明信片。
- Go / Rust 静态编译程序 → 直接用 scratch(0B) 或 distroless
- Python / Node.js / Java 应用 → 优先选 alpine(~5–8MB)或官方 -slim 版(如
python:3.11-slim,约 50MB) - 需要 glibc 兼容性时 → 用 debian:stable-slim(~25MB),避开 full 版本
用多阶段构建,只带“能跑起来”的东西进最终镜像
编译环境和运行环境必须分离。否则,golang:1.21 或 maven:3.8 这类带完整工具链的镜像会直接打进最终产物。
- 第一阶段:用完整镜像编译源码(含 Go、JDK、npm 等)
- 第二阶段:从
scratch、alpine或distroless开始,只COPY --from=builder编译好的二进制或打包产物 - 避免在最终镜像中出现
gcc、vim、curl等开发/调试工具
控制层数 + 清理同步做,别让缓存留在镜像里
Docker 每条指令(RUN、COPY 等)都新增一层,而删除操作只是标记“已删”,不释放空间。
- 合并多个
RUN:把安装 + 清理写在同一行,例如RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* - 所有包管理器加清理参数:
apk add --no-cache、pip install --no-cache-dir、npm ci --no-cache - 不要分两步写:
RUN npm install再RUN rm -rf node_modules/.cache—— 第二步不会删掉第一步层里的内容
验证和定位,用 docker history 找出哪一层最胖
执行 docker history your-image,看各层大小和对应指令。体积突增的那一层,就是问题源头。
- 如果某层显示 300MB+,大概率是 COPY 了整个
node_modules或未清理的构建产物 - 检查是否漏了
.dockerignore,避免把git目录、logs/、tests/打包进去 - 用
docker run --rm -it your-image sh进去手动查看文件分布,确认有没有残留的/tmp、/root/.cache等











