1. 概述

Docker 镜像 是容器的模板,包含应用、依赖库以及软件安装包。压缩 Docker 镜像的主要目的是减少其体积、层级数量和占用的存储空间,使其更加轻量

本文将介绍压缩 Docker 镜像的几种常用方法,包括:

  • 使用轻量级基础镜像 创建新镜像
  • 使用 docker exportdocker import 基于现有容器创建更小的镜像
  • 使用多阶段构建(Multi-stage Build) 在构建过程中剔除不必要的文件和依赖
  • 使用 docker-squash 工具 对现有镜像进行压缩
  • 使用 docker save 优化镜像归档时的存储空间

要复现本文示例,只需在 Linux 环境下安装好 Docker 即可。


2. 使用轻量级基础镜像

创建新镜像时,首选轻量级基础镜像

例如,如果你只需要 Ubuntu 的 UTF-8 支持,可以使用最小化的 Ubuntu 镜像。在 Dockerfile 中通过 FROM 指令指定:

FROM ubuntu

同理,对于 Alpine Linux,可以使用更小的 alpine 镜像。


3. 使用 docker exportdocker import

docker export 命令可将容器文件系统导出为 tar 包,随后通过 docker import 导入为新镜像。这种方法会丢弃容器的 volumes 数据,并将镜像压缩为单一层级,从而减少镜像体积。

示例操作:

  1. 拉取 mysql 镜像:
docker pull mysql
  1. 查看镜像大小:
docker images

输出示例:

REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
mysql        latest    2c849dee4ca9   4 weeks ago   859MB
  1. 运行容器:
docker run --name mysql-db -e MYSQL_ROOT_PASSWORD=mysql -d mysql
  1. 导出容器为 tar 文件:
docker export -o mysql-db.tar mysql-db
  1. 导入 tar 文件生成新镜像:
docker import mysql-db.tar mysql-db:imported
  1. 或者直接管道操作,避免中间文件:
docker export mysql-db | docker import - mysql:flattened
  1. 查看镜像大小变化:
docker images

输出示例:

REPOSITORY   TAG         IMAGE ID       CREATED          SIZE
mysql        flattened   6199c9a961a9   10 seconds ago   830MB
mysql        latest      2c849dee4ca9   4 weeks ago      859MB

效果:镜像体积减少约 29MB,层级变为 1 层


4. 使用多阶段构建(Multi-Stage Build)

多阶段构建允许我们在一个 Dockerfile 中使用多个 FROM 指令,每个阶段可以独立构建,最终只保留需要的构建产物

示例:Go 编译镜像

原始单阶段构建 Dockerfile:

ARG GOLANG_VER=1.8
FROM golang:${GOLANG_VER} as builder
WORKDIR /go/src/app
COPY . .
RUN go-wrapper download 
RUN go-wrapper install
CMD ["/go/bin/app"]

构建后镜像大小约为 2.92GB。

使用多阶段构建优化:

ARG GOLANG_VER=1.8
FROM golang:${GOLANG_VER} as builder
WORKDIR /go/src/app
COPY . .
RUN go-wrapper download 
RUN go-wrapper install

FROM scratch
COPY --from=builder /go/bin/app /app
CMD ["/app"]

构建并查看镜像大小:

docker build -t hello .
docker images

输出示例:

REPOSITORY   TAG         IMAGE ID       CREATED              SIZE
hello        latest      df4329120a36   About a minute ago   1.56MB

效果:镜像体积从 2.92GB 缩减到 1.56MB


5. 使用 docker-squash 工具

docker-squash 是一个 Python 工具,用于压缩现有镜像。它通过合并层级、删除临时文件来减少镜像大小。

安装与使用:

  1. 安装 Python 和 pip:
sudo apt install python3
sudo apt install python3-pip
  1. 创建虚拟环境并激活:
python3 -m venv docker-squash-env
source docker-squash-env/bin/activate
  1. 安装工具:
pip install docker-squash
  1. 压缩镜像:
docker-squash -t mysql:squashed mysql
  1. 查看镜像大小变化:
docker images

输出示例:

REPOSITORY   TAG         IMAGE ID       CREATED              SIZE
mysql        squashed    9cffd364951a   About a minute ago   830MB
mysql        latest      2c849dee4ca9   4 weeks ago          859MB

⚠️ 注意:docker-squash 实际上也是基于 docker exportdocker import 实现的


6. 使用 docker save

docker save 可将镜像保存为 tar 包,结合 gzip 压缩可进一步减少存储空间。适用于归档多个镜像而非容器

示例:

  1. 保存镜像为压缩包:
docker save mysql:latest | gzip > mysql.tar.gz
  1. 查看文件大小:
ls -l

输出示例:

-rw-rw-r--   1 ubuntu ubuntu 254347383 May 16 23:07 mysql.tar.gz
  1. 删除镜像:
docker image rm mysql
  1. 从 tar.gz 恢复镜像:
docker load < mysql.tar.gz

效果:压缩归档显著减少磁盘占用,便于镜像迁移与备份


7. 总结

压缩 Docker 镜像的方法多种多样,选择时应根据具体场景:

方法 适用场景 优点 缺点
使用轻量级基础镜像 新镜像构建 简单有效 仅适用于新镜像
docker export + import 现有容器导出为镜像 快速扁平化 丢失历史信息
多阶段构建 编译型语言项目 构建最小运行镜像 需修改 Dockerfile
docker-squash 已有镜像压缩 自动合并层级 需额外安装工具
docker save 归档或迁移镜像 压缩存储空间 不改变镜像结构

根据实际需求选择合适的方法,能有效提升镜像效率、节省资源。

完整命令示例可参考 GitHub 示例仓库


原始标题:How to Flatten a Docker Image