简介

Docker 是一种容器引擎,可以在容器内运行应用程序。优化 Docker 镜像大小的好处: - 减少安全风险 - 加快镜像传输速度 - 缩短部署时间

本指南提供 10 种减少 Docker 镜像大小的实用方法和可执行命令。

1. 最小化镜像层

原理

Dockerfile 中的每个 FROM、RUN、COPY 命令都会创建一个单独的层,增加镜像大小和构建时间。

优化前(多层)

FROM ubuntu:latest
RUN apt update -y
RUN apt install unzip -y
RUN apt install curl -y
RUN apt install python3 -y

优化后(单层)

FROM ubuntu:latest
RUN apt update -y && \
    apt install unzip -y && \
    apt install curl -y && \
    apt install python3 -y

执行命令

# 构建优化后的镜像
docker build -t optimized-image:v1 .

# 查看镜像大小
docker images optimized-image:v1

# 查看镜像层信息
docker history optimized-image:v1

2. 使用 Docker Squash 减小镜像大小

原理

Docker 在构建镜像时创建很多层。压缩有助于在逻辑层中组织镜像,减少不必要的层。

安装 docker-squash

# 安装 docker-squash 工具
pip install docker-squash

使用命令

# 压缩现有镜像
docker-squash image:old -t image:new

# 示例:压缩 nginx 镜像
docker-squash nginx:latest -t nginx:squashed

# 比较压缩前后的大小
docker images | grep nginx
```  

## 3. 使用较小的基础镜像

### 原理
选择更小的基础镜像是减小 Docker 镜像大小最直接的方法。

### 镜像大小对比
- `python:3.9` ≈ 1.3 GB
- `python:3.9-slim` ≈ 1 GB
- `python:3.9-alpine` ≈ 49 MB

### 查看镜像大小命令
```bash
# 拉取不同版本的 Python 镜像
docker pull python:3.9
docker pull python:3.9-slim
docker pull python:3.9-alpine

# 比较镜像大小
docker images | grep python

# 查看具体镜像信息
docker inspect python:3.9-alpine | grep Size

Dockerfile 示例

# 使用 Alpine 基础镜像
FROM python:3.9-alpine

# 安装依赖
RUN pip install --no-cache-dir flask

# 复制应用代码
COPY app.py /app/
WORKDIR /app

# 运行应用
CMD ["python", "app.py"]

4. 使用多阶段构建

原理

多阶段构建将 Dockerfile 分成多个阶段,只将必要的工件传递到最终镜像,显著减小镜像大小。

Dockerfile 示例(Node.js 应用)

# Stage 1: 构建阶段
FROM node:14.17-alpine3.14 as build

# 设置工作目录
WORKDIR /home/app

# 复制源代码
COPY public ./public/
COPY src ./src/
COPY package*.json ./

# 安装构建依赖
RUN apk add --no-cache g++ make python3
RUN npm install --silent

# 构建应用
RUN npm run build

# Stage 2: 运行阶段
FROM nginx:stable-alpine

# 复制 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 从构建阶段复制构建结果
COPY --from=build /home/app/build /usr/share/nginx/html

# 暴露端口
EXPOSE 80

# 启动命令
CMD ["nginx", "-g", "daemon off;"]

执行命令

# 构建多阶段镜像
docker build -t multi-stage-app:latest .

# 查看镜像大小
docker images multi-stage-app:latest

# 运行容器
docker run -d -p 80:80 multi-stage-app:latest

# 查看构建历史(只显示最终阶段)
docker history multi-stage-app:latest

5. 使用 –no-install-recommends 标志

原理

apt install 命令默认会安装推荐包,使用 --no-install-recommends 标志可以避免安装不必要的推荐包。

Dockerfile 示例

FROM ubuntu:latest

# 优化的包安装方式
RUN apt update -y && \
    apt install -y --no-install-recommends \
        unzip \
        curl \
        python3 \
        python3-pip && \
    rm -rf /var/lib/apt/lists/*

Alpine 系统对应命令

FROM alpine:latest

# Alpine 使用 --no-cache 标志
RUN apk add --no-cache \
        unzip \
        curl \
        python3 \
        py3-pip

执行命令

# 构建优化镜像
docker build -t optimized-ubuntu:latest .

# 比较镜像大小
docker images | grep ubuntu

# 进入容器检查安装的包
docker run -it optimized-ubuntu:latest bash
apt list --installed | wc -l

6. 清理 APT 缓存

原理

apt update 会下载包列表到 /var/lib/apt/lists/,安装完成后删除这些缓存文件可以减小镜像大小。

Dockerfile 示例

FROM ubuntu:latest

# 在同一个 RUN 指令中安装包并清理缓存
RUN apt update -y && \
    apt install -y --no-install-recommends \
        unzip \
        curl \
        python3 \
        python3-pip && \
    rm -rf /var/lib/apt/lists/*

其他清理命令

# 更全面的清理
RUN apt update -y && \
    apt install -y --no-install-recommends package-name && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

执行命令

# 构建镜像
docker build -t clean-image:latest .

# 查看镜像大小
docker images clean-image:latest

# 检查缓存目录是否为空
docker run --rm clean-image:latest ls -la /var/lib/apt/lists/

# 比较清理前后的大小差异
docker history clean-image:latest

7. 使用 .dockerignore 文件

原理

.dockerignore 文件可以防止不必要的文件被复制到 Docker 镜像中,减小镜像大小和构建时间。

.dockerignore 文件示例

# 版本控制
.git
.gitignore
.gitattributes

# 文档文件
*.md
README*
CHANGELOG*
LICENSE*

# 日志和缓存
logs/
*.log
.cache/
.npm/
node_modules/.cache/

# 开发工具配置
.vscode/
.idea/
*.swp
*.swo

# 测试文件
tests/
*.test.js
*.spec.js
coverage/

# 临时文件
*.tmp
*.temp
.DS_Store
Thumbs.db

# 环境文件
.env.local
.env.development
.env.test

# 构建产物(如果不需要)
dist/
build/
target/

执行命令

# 创建 .dockerignore 文件
cat > .dockerignore << EOF
.git
*.md
logs/
node_modules/.cache/
.env.local
EOF

# 查看构建上下文大小(构建前)
du -sh .

# 构建镜像
docker build -t app-with-dockerignore:latest .

# 检查哪些文件被忽略
docker build --no-cache -t test . 2>&1 | grep "Sending build context"

# 进入容器检查文件
docker run --rm -it app-with-dockerignore:latest ls -la
```  

## 8. 优化 COPY 和 RUN 指令顺序

### 原理
将变化频繁的文件(如应用代码)的 COPY 指令放在变化较少的指令(如依赖安装)之后,可以更好地利用 Docker 的层缓存机制。

### 优化前(缓存效率低)
```dockerfile
FROM ubuntu:latest

# 应用代码变化频繁,放在前面会导致后续层缓存失效
COPY . /app

# 依赖安装,变化较少但缓存经常失效
RUN apt update -y && \
    apt install -y --no-install-recommends \
        python3 \
        python3-pip && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app
RUN pip install -r requirements.txt

优化后(缓存效率高)

FROM ubuntu:latest

# 先安装系统依赖(变化较少)
RUN apt update -y && \
    apt install -y --no-install-recommends \
        python3 \
        python3-pip && \
    rm -rf /var/lib/apt/lists/*

# 先复制依赖文件
COPY requirements.txt /app/
WORKDIR /app

# 安装 Python 依赖
RUN pip install --no-cache-dir -r requirements.txt

# 最后复制应用代码(变化最频繁)
COPY . /app

执行命令

# 第一次构建
docker build -t optimized-cache:v1 .

# 修改应用代码后重新构建(观察缓存使用情况)
echo "# Updated code" >> app.py
docker build -t optimized-cache:v2 .

# 查看构建历史和缓存使用
docker history optimized-cache:v2

# 比较构建时间
time docker build --no-cache -t no-cache-test .
time docker build -t cache-test .

9. 安装后清理临时文件

原理

下载、解压、编译等过程会产生临时文件,安装完成后及时删除这些文件可以显著减小镜像大小。

AWS CLI 安装示例

FROM ubuntu:latest

# 安装 AWS CLI v2 并清理临时文件
RUN apt update && \
    apt install -y --no-install-recommends curl unzip && \
    curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" && \
    unzip awscliv2.zip && \
    ./aws/install && \
    rm -rf awscliv2.zip aws/ && \
    apt remove -y curl unzip && \
    apt autoremove -y && \
    rm -rf /var/lib/apt/lists/*

Node.js 应用示例

FROM node:16-alpine

WORKDIR /app

# 复制 package.json 并安装依赖
COPY package*.json ./
RUN npm ci --only=production && \
    npm cache clean --force && \
    rm -rf /tmp/*

# 复制应用代码
COPY . .

Python 应用示例

FROM python:3.9-slim

# 安装编译依赖、Python 包,然后清理
RUN apt update && \
    apt install -y --no-install-recommends \
        gcc \
        g++ \
        && \
    pip install --no-cache-dir numpy pandas && \
    apt remove -y gcc g++ && \
    apt autoremove -y && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

执行命令

# 构建镜像
docker build -t clean-install:latest .

# 查看镜像大小
docker images clean-install:latest

# 检查临时文件是否被清理
docker run --rm clean-install:latest find /tmp -type f
docker run --rm clean-install:latest ls -la /var/lib/apt/lists/

# 进入容器验证软件是否正常安装
docker run --rm -it clean-install:latest aws --version
```  

## 10. 使用 Docker 镜像优化工具

### 原理
专业的镜像优化工具可以自动分析和优化 Docker 镜像,发现人工难以察觉的优化点。

### Dive - 镜像层分析工具

#### 安装 Dive
```bash
# 使用 Docker 运行 Dive
docker run --rm -it \
    -v /var/run/docker.sock:/var/run/docker.sock \
    wagoodman/dive:latest <image-name>

# 或者下载二进制文件(Linux)
wget https://github.com/wagoodman/dive/releases/download/v0.10.0/dive_0.10.0_linux_amd64.deb
sudo apt install ./dive_0.10.0_linux_amd64.deb

# macOS 使用 Homebrew
brew install dive

使用 Dive 分析镜像

# 分析镜像层
dive nginx:latest

# 分析本地构建的镜像
dive my-app:latest

# 导出分析报告
dive --ci my-app:latest

Docker Slim - 镜像压缩工具

安装 Docker Slim

# 下载并安装 Docker Slim
curl -sL https://raw.githubusercontent.com/slimtoolkit/slim/master/scripts/install-slim.sh | sudo -E bash -

# 或使用 Docker 运行
docker run -it --rm \
    -v /var/run/docker.sock:/var/run/docker.sock \
    dslim/slim build my-app:latest

使用 Docker Slim 优化镜像

# 基本优化
slim build my-app:latest

# 带 HTTP 探测的优化
slim build --http-probe my-web-app:latest

# 自定义优化选项
slim build --include-path /app --exclude-path /tmp my-app:latest

# 查看优化结果
docker images | grep slim

在线 Dockerfile 优化工具

使用 fromlatest.io

# 上传 Dockerfile 到 https://www.fromlatest.io/ 进行在线分析

# 或使用 curl 提交分析
curl -X POST \
    -H "Content-Type: application/json" \
    -d '{"dockerfile": "'$(base64 -w 0 Dockerfile)'"}' \
    https://www.fromlatest.io/api/analyze

综合优化脚本

#!/bin/bash
# docker-optimize.sh - Docker 镜像优化脚本

IMAGE_NAME=$1

if [ -z "$IMAGE_NAME" ]; then
    echo "Usage: $0 <image-name>"
    exit 1
fi

echo "=== 原始镜像信息 ==="
docker images $IMAGE_NAME

echo "=== 使用 Dive 分析镜像 ==="
dive $IMAGE_NAME

echo "=== 使用 Docker Slim 优化 ==="
slim build $IMAGE_NAME

echo "=== 优化后镜像对比 ==="
docker images | grep -E "($IMAGE_NAME|slim)"

echo "=== 清理中间镜像 ==="
docker image prune -f

执行命令

# 使脚本可执行
chmod +x docker-optimize.sh

# 运行优化脚本
./docker-optimize.sh my-app:latest

# 比较优化前后的大小
 docker images | grep my-app

总结

优化效果对比

优化方法 预期减小幅度 适用场景
最小化镜像层 5-10% 所有项目
使用 Alpine 基础镜像 50-80% 对兼容性要求不高的项目
多阶段构建 60-90% 需要编译的应用
清理包管理器缓存 10-50MB 使用 apt/yum 的镜像
使用 .dockerignore 取决于项目 所有项目
Docker Slim 30-70% 生产环境镜像

最佳实践检查清单

# 创建优化检查脚本
cat > docker-checklist.sh << 'EOF'
#!/bin/bash
echo "=== Docker 镜像优化检查清单 ==="

# 检查基础镜像
echo "1. 检查是否使用了最小的基础镜像"
grep -i "FROM" Dockerfile

# 检查层数
echo "2. 检查 RUN 指令数量(建议合并)"
grep -c "^RUN" Dockerfile

# 检查是否有清理命令
echo "3. 检查是否清理了包管理器缓存"
grep -i "rm.*apt.*lists\|apt.*clean\|yum.*clean" Dockerfile

# 检查 .dockerignore
echo "4. 检查是否存在 .dockerignore 文件"
ls -la .dockerignore 2>/dev/null || echo "未找到 .dockerignore 文件"

# 检查是否使用了 --no-install-recommends
echo "5. 检查是否使用了 --no-install-recommends"
grep -i "no-install-recommends" Dockerfile

echo "=== 检查完成 ==="
EOF

chmod +x docker-checklist.sh
./docker-checklist.sh

快速优化命令集合

# 一键优化现有镜像
function optimize_docker_image() {
    local image_name=$1
    
    echo "开始优化镜像: $image_name"
    
    # 使用 Docker Slim 优化
    if command -v slim &> /dev/null; then
        echo "使用 Docker Slim 优化..."
        slim build $image_name
    fi
    
    # 清理未使用的镜像
    echo "清理未使用的镜像..."
    docker image prune -f
    
    # 显示优化结果
    echo "优化完成,当前镜像列表:"
    docker images | grep $image_name
}

# 使用示例
# optimize_docker_image my-app:latest

通过应用这些优化技巧,您可以显著减小 Docker 镜像的大小,提高部署效率和安全性。建议根据项目的具体需求选择合适的优化方法。