如何减小 Docker 镜像大小:DevOps 工程师的最佳实践和技巧
目录
- 为什么减少 Docker 镜像大小很重要
- 从最小基础镜像开始
- 多阶段构建
- 避免安装不必要的依赖项
- 用于
.dockerignore
排除不必要的文件 - 优化 Dockerfile 中的层
- 安装软件包后清理
- 使用较小的语言运行时
- 压缩图像层
- 删除调试信息
- 定期审核你的图像
- 高级技巧
- 结论
在DevOps 领域,优化Docker 镜像对于高效部署和编排应用程序至关重要。减小 Docker 镜像的大小可以提高速度、降低存储成本并简化 CI/CD 流水线。本指南将引导您了解减小 Docker 镜像大小的最佳实践,并提供一些技巧和策略,帮助您创建精简高效的镜像。
为什么减少 Docker 镜像大小很重要
- 更快的构建:更小的图像可以缩短构建时间并加快部署速度。
- 降低带宽和存储成本:大型图像在网络上传输需要更长的时间,并且需要更多的存储空间,这可能会变得昂贵。
- 更快的容器启动时间:更小的图像可以加快容器启动速度,这在容器需要快速扩展的动态环境中至关重要。
- 提高安全性:通过限制可能存在漏洞的不必要的软件和依赖项,减小图像大小可以最大限度地减少攻击媒介。
1.从最小基础镜像开始
基础镜像是 Docker 镜像的基础。选择轻量级基础镜像可以显著减小镜像的整体大小。请考虑以下基础镜像:
- Alpine Linux:Alpine Linux 是最受欢迎的极简 Docker 镜像选择之一,其大小约为 5MB,而 Ubuntu 镜像则高达 200MB。它的设计理念是简洁和安全,但需要注意的是,使用 Alpine 可能需要额外编译某些依赖项。
例子:
FROM alpine:3.18
- Distroless:Google 的 Distroless 镜像是极简容器的另一个绝佳选择。这些镜像不包含操作系统 Shell,专为安全运行应用程序而构建。
例子:
FROM gcr.io/distroless/base
2.多阶段构建
多阶段构建允许您在 Dockerfile 中使用多FROM
条指令,从而有效地将构建过程分解为多个阶段。这对于编译代码并仅将最终生成的工件复制到生产镜像(从而留下不必要的依赖项)尤其有用。
多阶段构建示例:
# Stage 1: Build
FROM golang:1.19 AS builder
WORKDIR /app
COPY . .
RUN go build -o main .
# Stage 2: Production
FROM alpine:3.18
WORKDIR /app
COPY --from=builder /app/main /app/
CMD ["./main"]
在此示例中,构建依赖项(例如 Golang 和源代码)仅在第一阶段存在。最终镜像仅包含已编译的二进制文件和最小的 Alpine 基础版本,因此镜像体积更小。
3.避免安装不必要的依赖项
安装软件包或库时,仅包含应用程序运行所需的软件包或库。避免在最终镜像中安装开发依赖项。您可以使用类似Debian 镜像中--no-install-recommends
的工具来避免安装额外的软件包。apt-get
例子:
RUN apt-get update && apt-get install --no-install-recommends -y \
curl \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
这种方法可以防止安装推荐但不必要的包,从而减少图像大小。
4.用于.dockerignore
排除不必要的文件
与 类似.gitignore
,该.dockerignore
文件有助于从 Docker 构建上下文中排除不必要的文件和目录,防止它们被复制到您的镜像中。
示例.dockerignore
文件:
node_modules
.git
.env
tmp/
logs/
通过排除这些文件,您可以显著减少图像的大小并加快构建过程。
5.优化 Dockerfile 中的层
Dockerfile 中的每一行都会在最终镜像中创建一个新的层。为了最小化镜像大小,请尽可能将多个命令合并为一条RUN
指令。这有助于避免在中间层中堆积未使用的文件。
优化前的示例:
RUN apt-get update
RUN apt-get install -y python3
RUN apt-get clean
优化后示例:
RUN apt-get update && apt-get install -y python3 && apt-get clean
通过组合这些命令,您可以减少层数并消除原本会被缓存的临时文件。
6.安装软件包后清理
在镜像构建过程中,通常会创建缓存或日志等临时文件,这会导致镜像体积膨胀。安装软件后,请务必清理包管理器缓存和其他临时文件。
对于基于 Debian 的图像:
RUN apt-get update && apt-get install -y python3 && apt-get clean && rm -rf /var/lib/apt/lists/*
对于基于 Alpine 的图像:
RUN apk add --no-cache python3
使用--no-cache
withapk
可确保不创建临时缓存文件,从而保持图像大小最小。
7.使用较小的语言运行时
如果您的应用程序是用 Python、Node.js 或 Java 等语言编写的,请考虑使用较小的运行时镜像。许多语言都提供“slim”或“alpine”版本的运行时。
例子:
# Instead of using this:
FROM python:3.11
# Use the slim version:
FROM python:3.11-slim
这些精简版本删除了不必要的组件,同时仍然提供语言运行时的核心功能。
8.压缩图像层
Docker 会在构建过程中自动压缩镜像层。不过,您也可以手动使用压缩工具进一步优化压缩效果。例如,在安装软件包或二进制文件时,您可以利用gzip
或tar
等压缩工具在将文件复制到最终镜像之前最小化文件大小。
9.删除调试信息
如果您的应用程序包含调试符号或元数据,则在生产环境中通常不需要它们。删除这些数据可以节省空间。
例子:
RUN strip /path/to/binary
10.定期审核你的图像
随着时间的推移,您的镜像可能会因为依赖项过期或未使用的软件而变得臃肿。请使用 和 等工具docker image ls
定期docker image prune
审核和清理旧镜像。
您还可以使用 Docker 的内置--squash
标志将所有层合并为一个层,以减小尺寸,尽管目前它还处于实验阶段。
修剪未使用的图像:
docker image prune -f
高级技巧
11.使用 Docker 镜像扫描
Docker Scout 等工具或第三方服务(例如 Trivy 或 Clair)可以分析 Docker 镜像中的漏洞和过时的软件包。这些工具通常会提供建议,以减少不必要的库和依赖项。
12.使用 OverlayFS 和共享层
在 Kubernetes 或其他编排环境中,您可以使用 OverlayFS 跨镜像共享层。此文件系统允许 Docker 仅存储容器层之间的差异,从而减少磁盘总大小。
13.考虑Unikernels
如果需要极致的尺寸优化,可以考虑使用 unikernel。这些是单一用途的轻量级虚拟机,仅打包应用程序及其所需的最少操作系统组件。它们比传统的 Docker 容器小得多,但实现起来更复杂。
结论
优化 Docker 镜像大小是维护高效可扩展容器化环境的关键。通过从最小基础镜像入手,利用多阶段构建并清理不必要的文件,您可以大幅缩减镜像大小。遵循这些最佳实践不仅可以提升部署性能,还能增强安全性并降低成本。
通过定期审核和优化 Docker 镜像,您可以确保容器精简、安全且可立即投入生产。这些步骤将节省带宽、缩短启动时间,并为您的 DevOps 流水线提供更高效的开发工作流程。
通过应用这些技术,您可以帮助 DevOps 工程师创建优化的 Docker 镜像,从而提高应用程序的整体效率。更小的镜像不仅部署速度更快,还能在云原生环境中提高安全性、可靠性和成本效益。
👤 作者

加入我们的电报社区||在 GitHub 上关注我以获取更多 DevOps 内容!
文章来源:https://dev.to/prodevopsguytech/how-to-reduce-docker-image-size-best-practices-and-tips-for-devops-engineers-1ahg