Docker 镜像瘦身:多阶段构建 + .dockerignore 的实际收益
很多团队第一次把 Go 或 Python 服务打成镜像,都会得到一个几百 MB 甚至上 GB 的“全家桶”。本文用一组实测数据说明:多阶段构建加上 .dockerignore,通常能把镜像体积压到原来的十分之一左右。
一、镜像为什么会变大
镜像体积主要来自三块:基础镜像、构建工具链、构建上下文。用 ubuntu:22.04 做底子,光系统层就有 70 多 MB;编译时用到的 gcc、make、头文件和包管理器缓存会原样进入镜像层。更隐蔽的是构建上下文:如果目录里躺着 node_modules、.git、日志和测试数据,一句 COPY . . 会把它们全部打进镜像——即使后面再删除,也只是在新层里“标记删除”,体积并不会减少。
二、多阶段构建:编译环境不带上线
思路很简单:第一阶段用完整 SDK 镜像编译,第二阶段只把产物拷进精简运行镜像。以 Go 为例:第一阶段 FROM golang:1.22 AS builder,COPY 后执行 go build -o app .;第二阶段 FROM alpine:3.20,用 COPY --from=builder 只拷贝二进制。golang:1.22 超过 800 MB,alpine:3.20 只有 7 MB,最终镜像通常不到 20 MB。注意静态编译时要加 CGO_ENABLED=0,避免 alpine 缺 glibc 起不来。
Python 项目同理:第一阶段 pip install 到虚拟环境并编译 wheel,第二阶段用 python:3.12-slim 拷贝 site-packages,一般能从 1 GB 降到 200 MB 以内。
三、.dockerignore:先把上下文打扫干净
.dockerignore 的语法和 .gitignore 一致,放在 Dockerfile 同目录。一个实用起点:.git、node_modules、__pycache__、*.log、tests、docs、.venv。这一步不仅省体积,还能明显加快 build context 的上传速度——机器学习项目里几十 GB 的数据集,绝不该出现在 docker build 的输出里。
四、实测收益
同一个 Go 服务:单阶段、ubuntu 底镜像 856 MB;改成多阶段 + alpine + .dockerignore 后 18 MB,拉取时间从 40 秒降到 2 秒。镜像小了,K8s 滚动发布更快,本地和 CI 的缓存占用也更低。
五、小结
先写 .dockerignore 打扫上下文,再用多阶段构建分离编译与运行,最后选 slim/alpine 基础镜像。三步做完,多数服务的镜像能缩到原来的十分之一,这是性价比最高的容器优化手段。
- 点赞
- 收藏
- 关注作者
评论(0)