Docker镜像瘦身,减小建站环境镜像体积

为什么你的建站镜像越用越大

很多站长发现,一台服务器上跑几个网站后,Docker镜像动辄 1GB 以上,拉取慢、部署卡、磁盘告警。Docker镜像瘦身的核心思路只有一句话:只把运行时真正需要的东西放进最终镜像
本文从零基础出发,用 5 个可验证的步骤,帮你把典型 LNMP 建站环境镜像从 1GB+ 压缩到 200MB 以内,并给出每一步的验证命令。

先看清镜像里到底装了什么

动手之前,先知道空间被谁占了。
推荐用 dive 工具分析镜像每一层:

docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  wagoodman/dive:latest your-image:tag

左侧是层列表,右侧是文件树。
Ctrl+U 可以只看未使用的层。
常见浪费来源:编译工具链、缓存文件、日志、测试依赖、重复安装的包。

另一个快速检查方式:

docker history your-image:tag --no-trunc

输出里 SIZE 列超过 100MB 的层,基本都有优化空间。

五个直接可用的瘦身步骤

步骤1:把基础镜像换成 Alpine 或 slim 版本

Ubuntu 基础镜像约 77MB,Debian slim 约 30MB,Alpine 仅约 5MB。
以 Nginx 为例:

# 优化前
FROM nginx:latest

# 优化后
FROM nginx:1.25-alpine

Alpine 使用 musl libc,部分二进制可能不兼容。
如果遇到 not found 报错,改用 debian:bookworm-slim 作为折中方案。

步骤2:用多阶段构建隔离编译环境

编译 PHP 扩展、Node 依赖时,编译器和头文件只在构建阶段需要。
多阶段构建让最终镜像只保留产物:

# 阶段1:构建
FROM php:8.2-fpm AS builder
RUN apt-get update && apt-get install -y libzip-dev \
    && docker-php-ext-install zip

# 阶段2:运行
FROM php:8.2-fpm-alpine
COPY --from=builder /usr/local/lib/php/extensions/ \
     /usr/local/lib/php/extensions/
COPY --from=builder /usr/local/etc/php/conf.d/ \
     /usr/local/etc/php/conf.d/

验证方式:docker images 查看新镜像大小,通常能减少 50%-70%。

步骤3:合并 RUN 指令并清理缓存

Dockerfile 中每条 RUN 都会产生一层。
把安装、使用、清理写在同一层:

# 错误写法:产生3层,缓存留在镜像里
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*

# 正确写法:1层完成
RUN apt-get update && apt-get install -y --no-install-recommends curl \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

关键点:--no-install-recommends 避免安装推荐包,rm -rf 必须和安装在同一层才有效。

步骤4:配置 .dockerignore 排除无关文件

在项目根目录创建 .dockerignore

.git
node_modules
*.log
*.md
tests/
.env

COPY . . 会把这些文件全部打包进镜像。
加一行 .dockerignore,通常能省几十 MB。

步骤5:清理无用镜像和构建缓存

构建过程中产生的悬空镜像和缓存也占磁盘:

docker image prune -f
docker builder prune -f

如果想更彻底:

docker system df
docker system prune -a --volumes

注意prune -a 会删除所有未使用的镜像,生产环境请先确认没有正在运行的容器依赖它们。

避坑指南:这些操作反而会让镜像变大

  • 不要在 RUN 里用 apt-get upgrade:会更新所有包,产生大量新层,且破坏可复现性。
  • 不要先 COPY 再 RUN 安装依赖:代码变动会导致依赖层缓存失效,每次重新安装。正确顺序是先 COPY 依赖清单文件(如 package.jsoncomposer.json),安装后再 COPY 源码。
  • 不要把数据卷内容打进镜像:数据库文件、上传目录应通过 volume 挂载,不应出现在镜像里。
  • Alpine 不是万能药:某些需要 glibc 的二进制(如部分 Java 应用、Oracle 客户端)在 Alpine 上无法运行,此时应选择 slim 镜像而非强行换 Alpine。

怎么确认瘦身真的生效了

完成上述步骤后,执行以下命令对比:

docker images | grep your-image

记录优化前后的 SIZE 列。
同时验证容器能正常启动:

docker run -d --name test your-image:tag
docker logs test
docker exec test nginx -t   # 以 Nginx 为例验证配置

如果服务正常、日志无报错,说明瘦身没有破坏运行时依赖。
最后用 dive 再看一次,确认没有超过 50MB 的无效层。

常见疑问

Q:换成 Alpine 后 PHP 扩展装不上怎么办?

Alpine 的包管理是 apk,不是 apt
安装 PHP 扩展需要用 apk adddocker-php-ext-install 配合 apk add --no-cache 安装编译依赖。
如果扩展依赖 glibc,建议退回 php:8.2-fpm-slim

Q:多阶段构建后镜像启动报“找不到文件”怎么排查?

说明 COPY 路径没覆盖运行时需要的文件。
docker run --rm -it your-image sh 进入容器,手动执行启动命令,看具体缺哪个文件,再回到 Dockerfile 补 COPY。

Q:瘦身之后构建速度变慢了,正常吗?

多阶段构建会增加构建步骤,首次构建可能稍慢。
但合理利用缓存(先 COPY 依赖清单再安装)后,日常构建速度不会明显下降。
镜像小反而让推送和拉取更快。

分享到:
上一篇
Docker容器固定IP配置,内网容器互相访问
下一篇
Zabbix监控磁盘使用率,满盘自动告警
1
系统公告

泽御云中秋国庆双节活动上线:新购8折,拼团3.99元起

尊敬的用户:
泽御云“月满中秋·礼贺国庆”双节活动现已开启,活动时间为2026年9月23日至10月10日。 活动期间可享以下福利:
1. 常规云服务器新购使用优惠码“泽御中秋国庆同乐”,符合条件的订单享8折优惠。
2. 香港精品云服务器5人拼团低至3.99元,部分4核4G套餐3人拼团年付388元,续费同价。
3. 新用户购买年付云服务器,符合活动规则可赠送2个月使用时长。
4. 老用户续费季度赠15天,续费年度赠2个月;活动期间升级配置免收配置迁移手续费。
5. 推荐好友成功下单,符合条件的推荐人可获赠7天服务器使用时长。
6. 活动期间享宕机补偿标准翻倍、简单网站迁移协助及技术工单优先处理权益。
温馨提示:优惠码不适用于拼团套餐、活动轻量产品、年付订单及续费订单;拼团套餐为独立特价活动,不与赠时类福利叠加。赠送时长不可折现、退款或跨账户转移,具体规则以活动页面说明为准。
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意