Docker镜像越做越大?从多阶段构建到瘦身的四步做法
镜像刚开始只有几百MB,几个版本后就涨到1GB以上:拉取变慢、部署变慢、磁盘告警也跟着来。瘦身不是一次性大扫除,而是一套固定下来的构建习惯。下面四步,是我在线上项目里验证过的做法。
一、先看清镜像胖在哪里
动手前先量化。docker images看镜像大小,docker history 镜像名按层展开,看哪一层撑起了体积。大头通常有三类:基础镜像本身大、编译工具链留在了最终镜像里、日志和.git等文件被误打进构建上下文。
二、换小的基础镜像,别图省事
应用只需要运行环境时,别用带全套工具链的开发镜像。编译型语言最终只要二进制文件和少量运行时依赖,解释型语言用精简版基础镜像也多半够用。选镜像时多问一句:里面的东西运行真的用得上吗?用不上就别带进生产镜像。精简镜像往往没有调试工具,定位问题可用临时调试容器,而不是为调试方便把生产镜像做大。
三、多阶段构建:编译和运行分开
这是效果最明显的一招:编译和运行分在同一个Dockerfile的两个阶段写,编译阶段装工具链、拉依赖、编译产物;运行阶段只复制产物,不带走编译工具。示例如下:
FROM golang:1.22 AS builder
WORKDIR /app
COPY . .
RUN go build -o server ./cmd/server
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/server ./server
CMD ["./server"]
最终镜像只剩二进制文件和精简运行环境,体积常从几百MB降到几十MB。复制产物要明确路径,别把整个构建目录拷过去。
四、收紧构建上下文,少装一个算一个
COPY . .会把构建上下文全部发给构建进程,日志、大文件、测试数据很容易被顺带打进镜像。在项目根目录放.dockerignore排除不需要的文件,例如:
.git
*.log
node_modules
dist
*.md
另外,安装系统依赖尽量一次装完并清理缓存,多条命令合并到同一个RUN指令里,避免每层留下中间文件;依赖固定版本,避免上游更新让镜像悄悄变大。
五、定期清理与复核
瘦身不是做一次就完事。定期用docker image prune清理悬空镜像、docker builder prune清理构建缓存;生产节点结合磁盘水位告警巡检。每次发版后对比一下镜像大小,某个版本突然大几十MB就值得查一查。
核心就一句话:最终镜像只留运行必需的东西。按这四步做,多数项目的镜像能瘦掉一半以上,部署和磁盘压力都会明显改善。
- 点赞
- 收藏
- 关注作者
评论(0)