第二部分:Docker 镜像构建技巧实战

📝 前言

欢迎来到《云原生之旅第二部分》的第三篇技术文章!

在前两篇中,我们已经一起探索了 Docker 的基础知识和进阶功能:

现在,我们将继续 Docker 镜像的深度探索之旅。

本篇将聚焦五个关键实战技巧,这些技巧都是我在实际企业级应用开发中积累的宝贵经验。

无论您是开发人员、DevOps 工程师还是系统管理员,掌握这些技巧都将显著提升您的工作效率,帮助您构建更高效、更安全、更专业的容器化应用。

🧭 背景介绍

在云原生时代,Docker 镜像已成为应用交付的标准格式。

根据 2023 年CNCF的云原生调查报告显示,超过 90% 的企业在生产环境中使用容器技术。

—— 数据来源:https://www.cncf.io/reports/cncf-annual-survey-2023

随着容器技术的普及,然而在实际生产环境中,我们常常面临诸多挑战:构建速度缓慢导致 CI/CD 流水线效率低下、镜像体积过大造成存储和传输资源浪费、安全漏洞带来潜在风险、跨平台兼容性问题增加运维复杂度等。

这种差距往往导致资源浪费和安全风险。本文针对这些痛点,提供经过生产验证的解决方案。

📋 前提条件

在开始本教程前,请确保您已具备以下条件:

🧠 本章知识卡片

🚀 文章小节

1️⃣ 构建缓存优化

理解Docker分层构建

Docker 镜像采用分层存储机制,每一条 Dockerfile 指令都会创建一个新层,合理利用缓存可以显著加速构建过程。

镜像分层如下图所示:

一个完整的 Dockerfile 通常包含以下步骤:

选择一个基础镜像 → 复制源码到镜像内 → 安装依赖 → 设置启动命令。

缓存优化策略

对于每项指令,Docker 会检查是否可以重用之前构建中的相同指令。

如果发现之前已经执行过类似的指令,Docker 就不需要重新执行它,而是会使用缓存的结果。

让我们以上述的Dockerfile为例,原始文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# Node.js 官方镜像
# FROM node:20-alpine
FROM registry.cn-hangzhou.aliyuncs.com/lusyoe/node:20-alpine

# 设置工作目录
WORKDIR /app

# 复制源代码
COPY . .

# 安装依赖
RUN npm install

# 构建静态文件
RUN npm run build

# 暴露端口(根据您的应用配置调整)
EXPOSE 3000

# 启动应用
CMD ["npm", "start"]

以上文件存在的问题是构建顺序会失去缓存优势,导致每次代码变更时都需要重新安装所有依赖。

优化后的Dockerfile文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Node.js 官方镜像
# FROM node:20-alpine
FROM registry.cn-hangzhou.aliyuncs.com/lusyoe/node:20-alpine

# 设置工作目录
WORKDIR /app

# 复制package.json和package-lock.json
COPY package*.json ./

# 安装依赖
RUN npm install

# 复制源代码
COPY . .

# 构建静态文件
RUN npm run build

# 暴露端口(根据您的应用配置调整)
EXPOSE 3000

# 启动应用
CMD ["npm", "start"]

优化后的构建说明如下:

  • 先复制 package*.json:这样 Docker 可以缓存依赖安装层
  • 然后安装依赖:只有在package.json变更时才会重新执行
  • 最后复制源代码:代码变更不会影响依赖层

2️⃣ 多阶段构建

通过多个 FROM 指令将构建过程分为多个阶段,最终只保留必要的产物,可以大幅减小镜像体积。

这里还是以前端项目为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 多阶段构建 - 构建阶段
# FROM node:20-alpine AS builder
FROM registry.cn-hangzhou.aliyuncs.com/lusyoe/node:20-alpine AS builder

# 设置工作目录
WORKDIR /app

# 复制package.json和package-lock.json(如果存在)
COPY package*.json ./

# 安装依赖
RUN npm install

# 复制源代码
COPY . .

# 构建静态文件
RUN npm run build

# 生产阶段
FROM nginx:alpine
FROM registry.cn-hangzhou.aliyuncs.com/lusyoe/nginx:alpine

# 复制构建产物到 nginx 目录
COPY --from=builder /app/out /usr/share/nginx/html

# 复制nginx配置文件(可选)
# COPY nginx.conf /etc/nginx/nginx.conf

# 暴露端口
EXPOSE 80

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

配置说明:

  • AS builder:通过 AS builder 将该镜像标记为构建阶段。
  • —from=builder:通过 --from=builder 引用构建阶段生成的产物。

最终镜像仅包含运行所需静态文件,不包含 node 以及 npm 等构建编译工具。

完整项目示例代码:https://github.com/lusyoe/next-docker-demo

3️⃣ 基础镜像瘦身

镜像瘦身策略

选择最小化基础镜像:

  • alpine vs ubuntu:8MB vs 78MB
  • distroless镜像(Google提供的不含shell的极简镜像)
  • 清理不必要的文件:
1
2
3
RUN apt-get update && \
apt-get install -y --no-install-recommends python3 && \
rm -rf /var/lib/apt/lists/*

高级技巧

使用 docker-slim 工具:

1
2
3
4
# 从官网进行下载
# https://github.com/slimtoolkit/slim/releases
# 执行搜身命令
docker-slim build --target myapp:fat

4️⃣ 镜像安全扫描

容器镜像安全扫描(如使用 Trivy、Clair 等工具)是现代云原生开发和运维的关键实践。

本节介绍如何在本地开发和 CI/CD 环境时使用Trivy工具检查镜像。

本地开发时检查镜像

1
2
3
4
# 下载安装 Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin v0.65.0
# 检查镜像
trivy image nginx:latest

CI/CD 环境时检查镜像(Github/Gitea Action 示例)

1
2
3
4
5
6
- name: Scan with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: 'my-app:latest'
format: 'table'
exit-code: '1' # 发现高危漏洞时终止流程

5️⃣ 多平台构建

Buildx 是 Docker 官方推出的下一代镜像构建工具(基于 BuildKit),支持 多平台构建(ARM/AMD)缓存优化高级构建模式

最新版本 Docker 默认已集成了 Buildx,可通过以下命令查看其版本:

1
2
3
docker buildx version

github.com/docker/buildx v0.25.0 faaea65

创建 buildx 构建器

1
2
# 默认的 docker 引擎不支持多平台构建,因此需要先切换引擎
docker buildx create --name mybuilder --driver docker-container --use

构建并导出为本地镜像

1
2
3
4
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t next-docker-demo:multiarch \
--load .

构建并上传镜像

1
2
3
4
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t next-docker-demo:multiarch \
--push .

✅ 总结

通过本文的五个实战技巧,我们系统性地解决了Docker镜像构建中的核心问题:

  1. 构建缓存优化:可提升CI/CD效率,减少70%以上的构建时间
  2. 多阶段构建:能将镜像体积缩小90%以上,同时提高安全性
  3. 基础镜像瘦身:进一步优化资源利用率,降低安全攻击面
  4. 安全扫描:帮助建立持续的安全防护机制
  5. 多平台构建:为混合架构环境提供一致性的交付方案

这些技巧的组合使用,能够帮助团队建立专业级的容器化交付流程。

建议读者从最紧迫的痛点入手,逐步实施这些优化策略。