几个月之前,在为客户进行关键部署时,我们碰到了一个意外的问题:部署过程特别慢。问题的根源在于臃肿的Docker镜像。这不仅令人沮丧,还带来了我们无法承受的停机时间。
这段经历让我学到了重要的一课:小改动可以产生大影响。通过优化 Docker 镜像,我们成功地将部署时间缩短了一半,节省了存储费用,并提高了 CI/CD 流水线的整体效率。今天,我将分享我们实现这一转变所采取的策略。
……
为什么我们要优化 Docker 镜像?如果你曾经遇到过构建变慢、部署时间长或注册表空间中充斥着过大镜像的问题,你不是唯一一个遇到这种情况的人。那么,减少镜像大小的原因何其重要?
- 更快的构建: 开发周期变得更短,让您能够专注于重要的事情。
- 高效的存储: 更小的镜像占用的Docker注册表和机器上的磁盘空间更少。
- 更快的部署: 通过网络部署更小的镜像速度更快,更有效率。
- 增强的安全性: 组件更少,意味着潜在的安全漏洞也更少。
此处省略内容
那一天我们终于瘦身了Docker镜像我记得我们优化之后第一次运行 docker images
的时候。看到“优化前”和“优化后”的大小变化,就像健身几周后上秤称重一样——能明显感觉到变化,感觉非常有成就感。这种感觉真的很棒。
以下是我们的确切步骤,以实现那个转变:
……
7 种有效优化 Docker 镜像的方法1. 选择最小的基镜像
我们不再以 ubuntu:latest
或其他大型镜像为基础,而是切换到了 alpine
。这一改动将镜像大小从 800MB 减少到不到 30MB。
例子:
FROM alpine:latest # 从最新的 Alpine 镜像拉取基础镜像
点击全屏按钮,然后点击退出全屏按钮
……
2. 采用多阶段构建过程
在许多项目中,例如一个 React 应用程序,我们可能有一些构建所需的依赖项(如 Node.js 和 npm),这些依赖项仅在构建过程中需要,生产环境中则不需要。通过采用多阶段构建,我们可以将构建环境和运行时环境分开,从而生成更小的镜像。
示例:
在此示例中,我们将为一个 React 应用程序采用多阶段构建流程。
# 构建阶段
FROM node:16 AS builder
WORKDIR /app
COPY package.json package-lock.json ./
# 复制 package.json 和 package-lock.json 到当前目录下
RUN npm install
COPY . .
# 运行 npm 构建命令
RUN npm run build
# 运行时阶段
FROM nginx:alpine
# 从构建器阶段复制构建后的文件到 nginx 的 html 目录
COPY --from=builder /app/build /usr/share/nginx/html
# 启动 nginx 并设置守护进程为关闭状态
CMD ["nginx", "-g", "daemon off;"]
全屏 退出全屏
上面的Dockerfile
-
利用官方的 node:16 版本,安装所需的依赖,构建 React 应用,并生成静态内容。
- 第二个阶段使用更小的 nginx:alpine 镜像来提供已构建的 React 应用。
这种逐步的方法保证了最终镜像中仅包含必要的构建产物(构建文件夹),从而使镜像尽可能小,同时优化生产环境。
此处为空白或仅包含格式符号,请参见原文。
3. 清理不必要的文件
调试时,我们常常在构建中包含临时文件。通过添加一个 .dockerignore
文件,我们确保这些文件就不会被误打包进镜像里。
例如 .dockerignore:
node_modules # 忽略node_modules文件夹
*.log # 忽略所有.log文件
.git # 忽略.git文件夹
这些行用于在版本控制系统中排除不需要跟踪的文件和文件夹。
切换到全屏 退出全屏
此处为空
4. 合并并减少图层
每个 Dockerfile
中的指令(例如 RUN
、COPY
、ADD
)都会在 Docker 镜像中添加一个新的层。过多的层会导致镜像体积增大。通过将多个指令合并为一个 RUN
语句,这样可以减少层数并优化镜像。
示例:
不要写:
RUN apt-get update # 更新软件包列表
RUN apt-get install -y curl vim # 安装 curl 和 vim 工具
RUN apt-get clean # 清理 apt 缓存
RUN rm -rf /var/lib/apt/lists/* # 删除 apt 列表文件
切换到全屏模式 退出全屏
把它们合并成一个:
RUN apt-get update && apt-get install -y curl vim \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
点击进入全屏
点击退出全屏
这种方法尽量减少层数,并确保临时文件(如缓存)在同一层内被清除,从而使镜像文件更小且更整洁。
省略了部分内容
5. 避免安装不必要的依赖
最初,我们的Docker镜像包含了一些额外的库“以防万一”。随着时间的推移,我们意识到这导致了镜像变得过大以及不必要的安全隐患。通过只指定运行时实际需要的依赖项,我们让镜像变得更小和更安全。
例如,我们没有为每个项目安装许多库,而是关注最小的依赖,并避免安装不必要的包。
6. 这个步骤可以试试 docker-slim
.
docker-slim
成为了我们过程中的一个变革者。这个工具能自动分析你的镜像,并通过移除未使用的文件、二进制文件和库等不必要的部分来减小镜像的大小,而不会影响其功能。
我们用 docker-slim
将图像大小减少了最多 80%,这使得 docker-slim
成为我们优化策略中的重要工具。
要缩小图像的命令:
使用 docker-slim build <image-name>
命令来构建镜像。将 <image-name>
替换为实际的镜像名称。
docker-slim build <image-name>
点击这里进入全屏模式 点击这里退出全屏模式
7. 定期审查并修剪图像
Docker 镜像会随着时间的推移而积累,未使用的镜像或层会占据宝贵的磁盘空间。定期检查和清理未使用的镜像有助于保持环境整洁。
你可以通过运行下面的命令来删除多余的图片和图层:
清理未使用的镜像的命令示例:
docker system prune -f
这将强制删除Docker系统中未使用的资源。
进入全屏 退出全屏
删除所有未用图片的命令:
docker image prune -a -f # 删除所有未使用的 Docker 镜像
进入全屏退出全屏
通过将定期剪枝纳入你的日常工作,你可以确保你的 Docker 环境始终保持简洁高效。
衡量成功
在实施了这些优化之后,我们用docker images
命令来比较大小。结果令人惊讶。
- 优化之前: 1.2GB
- 优化之后: 250MB
不仅我们的部署更快了,云存储成本也降低了。
总结
优化 Docker 镜像可能看起来像是一个不重要的任务,但它能为你带来巨大的好处,特别是在工作流程上。不论你是独自开发还是在一个大团队中工作,这些策略都能带来真正的不同。
所以,你还等什么?跳进去看看你的 Dockerfile
,开始优化工作,享受更快捷部署带来的好处吧。
参考文献
📖 喜欢这篇博客吗? 你也可以在我的 Hashnode 上阅读我的文章,也可以在那里关注我了解更多技术见解!🚀
共同学习,写下你的评论
评论加载中...
作者其他优质文章