2.2 build 构建命令现场:上下文、标签与缓存


2.2 build 构建命令现场:上下文、标签与缓存

本节摘要:docker build 把 Dockerfile 与构建上下文变成一叠镜像层。本节从最小构建命令出发,讲清上下文是什么、-t 标签怎么起、缓存按什么规则命中,再逐个拆解 -f、--no-cache、--build-arg、--target 等高频义项,全程配可复现的构建会话与缓存失效排查现场。

改完一行 Dockerfile,重新 build,结果十分钟后还在下载依赖包——这个场景几乎每个团队都遇到过。问题不在构建本身,而在对"上下文"与"缓存"这两件事的理解。本节就从现场出发,把 docker build 的词条逐项展开:它读什么、算什么、缓存什么。

最小可用现场

先给一个能跑的完整例子。目录里放这样的 Dockerfile:

FROM debian:12-slim WORKDIR /app RUN apt-get update && apt-get install -y --no-install-recommends curl \ && rm -rf /var/lib/apt/lists/* COPY app.py . CMD ["python3", "app.py"]

构建命令与真实输出:

$ docker build -t myweb:0.1 . [+] Building 12.4s (10/10) FINISHED => [1/4] FROM docker.io/library/debian:12-slim => [2/4] WORKDIR /app => [3/4] RUN apt-get update && apt-get install -y ... curl => [4/4] COPY app.py . => exporting to image => => naming to docker.io/library/myweb:0.1 $ docker images myweb REPOSITORY TAG IMAGE ID CREATED SIZE myweb 0.1 8c4e21ab77d2 5 seconds ago 112MB

命令末尾那个点不是"文件在哪"的省写,它是构建上下文——docker 客户端把这个目录整个打包发给守护进程,Dockerfile 里的 COPY 只能从这个包里取文件。理解这点能解释很多怪现象:上下文目录里塞了几个 GB 的日志,构建一开始就卡住不动,因为光打包上传就要跑半天。

词条卡:docker build

docker build [OPTIONS] PATH | URL | -

义项(高频选项):

选项 含义 使用时机
-t 名字:标签 给结果打标签,可重复多次 几乎总是要写
-f 路径 指定 Dockerfile 位置 文件不叫默认名时
--no-cache 全量重建,忽略缓存 怀疑缓存陈旧时
--build-arg K=V 传入构建期变量 配合 ARG 指令
--target 阶段名 只构建到某阶段 多阶段构建调试
--platform 指定目标平台 交叉构建

构建上下文除了目录,还可以是远端地址或管道输入,日常九成场景就是那个点号。标签可一次打多个:-t myweb:0.1 -t myweb:latest,推送仓库时很省事。

现场一:上下文瘦身前后

$ ls -lh -rw-r--r-- 1 ops ops 2.3G app-logs.tar -rw-r--r-- 1 ops ops 156 Dockerfile -rw-r--r-- 1 ops ops 892 app.py $ docker build -t myweb:0.2 . ...(进度条在 Sending build context to Docker daemon 阶段停滞)

在上下文根放 .dockerignore,语法与常见忽略文件一致:

app-logs.tar *.log .git node_modules

再构建时上下文只有几 KB,Sending 阶段瞬间完成。这个文件不是可选项,而是 build 词条的固定搭配——它同时还是安全边界:密钥文件被 ignore 掉,才不会糊里糊涂烧进镜像层。

现场二:缓存命中与失效

现场二:缓存命中与失效

把现场跑出来对照:

$ echo "# touch" >> app.py $ docker build -t myweb:0.2 . => [2/4] WORKDIR /app CACHED => [3/4] RUN apt-get update && ... CACHED => [4/4] COPY app.py . 0.4s $ docker build -t myweb:0.2 --no-cache . => [3/4] RUN apt-get update && ... 48.2s

改了 app.py 后,前两层照样 CACHED,只有 COPY 及其后重建——这正是把"爱变的放后面"换来的效率。而 --no-cache 连依赖安装都重来,适合怀疑基础镜像或系统源出了变化的场合,代价是全程真跑。

现场三:--build-arg 与版本参数化

ARG NODE_VERSION=20 FROM node:${NODE_VERSION}-slim
$ docker build --build-arg NODE_VERSION=18 -t legacy:18 . $ docker build -t current:20 .

ARG 是构建期变量,镜像落地后即消失,与运行期的 ENV 不是一回事。用它可以不改编译器版本号,维护两条构建线。注意 ARG 必须在用到它的 FROM 之前声明才对 FROM 生效,这条规则是 build 报"invalid reference format"之外的另一类高频翻车点。

⚠️ 常见坑:把密码或令牌写进 ARG 传进去——它虽然不进最终环境变量,却会留在构建历史里,docker history 一查便知。凭据类输入交给构建器的 secret 机制或运行期挂载,别走 ARG。

本节要点回顾

  • 末尾参数是上下文不是路径:客户端把该目录打包发给守护进程,目录大小直接决定构建起步速度。
  • .dockerignore 是固定搭配:既给上下文瘦身,也防止敏感文件进层。
  • 缓存逐层比对:任何一层失效,其后所有层重建;指令顺序按"变化频率"升序排列。
  • --no-cache 是怀疑缓存时的全量重建,--build-arg 参数化构建期变量但不得携带凭据。
  • -t 可一次打多个标签,为肆部的推送词条铺路。

镜像造出来之后总有退役的一天:哪些能删、怎么删才不伤及无辜、离线机器上怎么把它送过去,2.3 的清理与搬运词条接手。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U