Docker 多阶段构建实战:把 Python 镜像从 900MB 瘦身到 120MB

举报
yd_229284667 发表于 2026/11/12 06:13:34 2026/11/12
【摘要】 一个 Flask 小服务的镜像竟有 900MB,根源是基础镜像太重、构建工具和缓存都留在了最终镜像里。本文用多阶段构建把构建与运行拆开,同一份代码从 900MB 瘦身到 120MB,并总结了路径写错、缺系统库、配置泄露三个常见坑。

上周我把一个几百行代码的 Python 小服务搬上容器,docker images 一看竟有 900MB。排查后发现问题不在业务代码,而在构建方式:基础镜像太重,构建工具和中间文件全留在了最终镜像里。改用多阶段构建后,同一份代码只剩 120MB 左右。这篇短文记录这次瘦身。

一、镜像为什么变胖

习惯从 python:3.12 完整镜像起手,它自带编译器和开发头文件,单基础层就有几百兆;pip install 又装了 gcc 等编译依赖,缓存和临时文件没有清理,也一层层留了下来。容器运行只需要最终产物,构建工具本来就不该跟着上船。

二、多阶段构建怎么做

把“构建”和“运行”拆开:第一阶段用完整镜像编译、安装依赖;第二阶段换干净的 slim 镜像,只把成果复制过来。Dockerfile 用 FROM … AS builder 命名第一阶段,再用 COPY --from=builder 搬文件,构建阶段装再多工具也不影响最终体积。

三、可以直接用的例子

项目只有主程序文件和依赖清单文件(Flask、requests)。

# 第一阶段:构建
FROM python:3.12 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
COPY . .
# 第二阶段:运行
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /install /usr/local
COPY --from=builder /app/app.py .
CMD ["python", "app.py"]

细节:pip 加 --no-cache-dir;–prefix=/install 把依赖装到固定目录,方便整目录复制;第二阶段只复制主程序文件,不复制整个构建目录。构建命令不变:docker build -t myapp:slim .,再用 docker images 对比。

四、三个坑

一是路径写错:–prefix 目录与 COPY --from 源路径必须一致,否则运行时报 ModuleNotFoundError,构建时却不报错。

二是缺系统库:slim 很精简,运行时可能缺 libpq、libssl 等动态库,在第二阶段用 apt-get install 补上即可,往往只多几兆。

三是泄露配置:COPY . . 会把 .env、证书带进镜像。用 .dockerignore 排除 .env、__pycache__、.git 和测试目录,既瘦身也更安全。

五、效果

重新构建后镜像从 900MB 降到 120MB 左右,启动没有变慢,健康检查一次通过。多阶段构建不是万能药:依赖本身很大、运行期需要编译器时,瘦身空间有限。但对大多数 Python Web 服务,这是一次投入小、收益确定的优化,值得作为默认写法。手头有臃肿镜像的话,按模板改一次,前后各跑一次 docker images 就能看到差别。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。