Docker 镜像体积从 110MB 降到 13MB 后端服务的瘦身

8 个服务镜像从平均 ~110MB 精简约 88%,降到平均 ~13MB。

一、以前 vs 现在:基底镜像

以前 现在
基底镜像 debian:bookworm-slim alpine:3.20
基底体积 ~70MB ~3.5MB
装了什么 ca-certificates ca-certificates + tzdata
运行用户 root 非 root(app 用户)

为什么选 alpine 而不是 distroless/scratch?

  • Go 服务是 CGO_ENABLED=0 纯静态二进制,任何最小基底都能跑

  • alpine 比 debian-slim 小约 90%,自带 busybox shell,容器里排查问题方便

  • apk add 装个证书就完事,无需包管理器红海

  • distroless/scratch 虽更小(2-3MB),但没有 shell,出问题无法进入排查

二、最终体积对比

服务 之前 (debian) 现在 (alpine) 节省
微服务 A ~177MB 19.0MB ~89%
微服务 B ~147MB 18.0MB ~88%
微服务 C ~133MB 16.0MB ~88%
微服务 D ~147MB 16.0MB ~89%
微服务 E ~37MB 10.0MB ~73%
微服务 F ~90MB 9.0MB ~90%
微服务 G ~80MB 9.0MB ~89%
微服务 H ~90MB 9.5MB ~89%
平均 ~110MB ~13MB ~88%

三、为什么以前那么大?

不是单纯的"debian 比 alpine 大"那点差距,真正的大头是 镜像里装了不必要的重量级工具

  1. 图片转 WebPffmpeg 实现,多个服务都要装 ffmpeg(含大量共享库 + 构建依赖)

  2. 硬件能力探测 调用了 ffmpeg -encoders,导致核心服务也要装 ffmpeg

  3. 浏览器依赖 被误打进容器------某些工具依赖只在独立的 CLI 工具中,本不该进容器镜像

四、瘦身三板斧

1. 基底换 alpine

Dockerfile 运行阶段:

dockerfile

复制代码
FROM alpine:3.20 AS runtime
RUN apk add --no-cache ca-certificates tzdata \
    && addgroup -S app && adduser -S -G app app
USER app
COPY --from=build /out/app /app
ENTRYPOINT ["/app"]

2. 图片转 WebP 前移到前端

前端上传前用 canvas / OffscreenCanvas 完成 WebP 转换:

  • 等比缩放到最大 1920px

  • 质量参数 0.6

  • GIF/WebP 原样跳过

后端改成纯 pass-through,不再调用 exec ffmpeg

额外收益: 上传前压缩节省了网络带宽和存储空间,绝大多数现代浏览器都支持 WebP。

3. 砍掉容器里根本不用的依赖

确认主服务不 import 某个工具模块 → 该模块的依赖(如浏览器)只保留在独立的 CLI 工具中,不进容器镜像。

五、验证结果

  • 所有镜像重建完成

  • 全部容器启动成功,进程日志无异常

  • 核心接口正常返回

  • 业务链路不受影响

六、还能不能更小?

可以,但投入产出比不高:

方案 收益 代价
distroless/scratch 再省 3-4MB 无 shell,排查问题困难,需从 gcr.io 拉取
去掉 tzdata 省 1-2MB 日志时间变 UTC
upx 压缩二进制 省十几 MB 增加复杂度,压缩后启动有额外开销

结论:alpine + 纯静态 Go + 前端处理图片 = 生产可用 + 最精简的甜点位。

七、核心经验

  1. 换基底镜像是最直接的瘦身手段 --- debian-slim → alpine,一步省 60+ MB

  2. 审视容器里真正需要什么 --- 不要把全量构建工具链带进运行镜像

  3. 能往前端推的就往前端推 --- 图片处理在浏览器端完成,后端只做透传

  4. 多阶段构建 + 非 root 用户 --- 安全与体积兼顾

  5. 定期审视依赖 --- 有些依赖只在特定场景使用,可以拆分到独立镜像

相关推荐
虎头金猫1 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
分布式存储与RustFS1 天前
MinIO 官方 Docker 镜像被移除:依赖它的项目该怎么办
docker·云原生·devops·对象存储·minio·分布式存储
AI职业加油站1 天前
AI智能体应用工程师证书:政策红利下的职业新风口
大数据·运维·人工智能·学习·职场发展
此冬歌咏1 天前
K8s 节点故障实战:优雅驱逐 31 秒,硬故障 331 秒,以及那个永远 Pending 的 Pod
运维·k8s
玉&心1 天前
通过Arthas在线诊断K8S中的内存及JVM等使用情况
docker·k8s·arthas
xing-xing1 天前
Docker容器中Nginx站点根目录网页配置访问
nginx·docker
-梅1 天前
linux(8) 软硬链接
linux·运维·服务器
赵文宇(温玉)1 天前
CoreDNS的hosts插件的缺行配置导致k8s集群异常
容器·kubernetes·rancher
guo_wen_qiang1 天前
上传本地镜像到harbor中
docker·容器·持续部署
张洛闻Eren1 天前
k8s云原生【第十课】:水平 Pod 自动扩缩容
运维·数据库·云原生·kubernetes·github