简介
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 镜像的大小,提高部署效率和安全性。建议根据项目的具体需求选择合适的优化方法。