Dockerfile 与构建

定义

Dockerfile(或 Containerfile)是一份构建说明书。它从一条 FROM 指令指定的基础镜像出发,按顺序执行复制文件、运行命令、设置环境等步骤,最终得到新的镜像。build 命令读取该文件以及构建上下文(通常是当前目录),在内容寻址缓存的帮助下复用未变化的步骤。

构建的输出仍然是镜像,不是正在运行的容器。要运行构建产物,需要另一次 run

问题背景

手工在一台已安装好的机器上「整理环境」,无法稳定地告诉另一台机器如何得到同一环境。把安装步骤写成可重复的指令,有两个直接效果:同一份文件在不同主机上应得到同一摘要;某一步失败时,可以定位到具体指令,而不是一整台不可描述的机器。

分层缓存进一步降低重复成本。若只有应用代码变化,基础系统与依赖层不必重做。

机制说明

指令与层的对应关系

常见指令及其作用:

指令 作用
FROM 指定基础镜像,构建的起点
COPY / ADD 把构建上下文中的文件放入镜像
RUN 在前一层之上执行命令,结果成为新层
ENV 设置镜像配置中的环境变量
WORKDIR 设置后续指令与容器启动时的工作目录
EXPOSE 声明容器意图监听的端口,本身不发布端口
CMD / ENTRYPOINT 指定默认入口进程

EXPOSE 经常被误解为「自动打开端口」。它只是元数据。真正把宿主端口映射到容器,要靠 run -p 或 Compose 中的 ports,见容器网络与端口发布

构建上下文与缓存

build 发送的上下文默认是 Dockerfile 所在目录(可用 .dockerignore 排除无关文件)。COPY . /app 会把上下文中的文件纳入该层的摘要。因此,上下文里多一个无关的日志文件,也可能使缓存失效。

缓存命中的条件是:前一层摘要相同,且本条指令及其输入相同。一旦某一步未命中,其后所有步骤通常都要重做。把变化频繁的 COPY 尽量放在后面,是控制构建时间的基本方法。

构建不等于运行

构建阶段执行的 RUN 发生在构建环境中,目的是产生层。这些命令的过程输出不是生产日志。生产入口由 CMDrun 时覆盖的命令决定。把密钥写进 Dockerfile 的 ENVRUN echo,会使密钥进入镜像层,随后随镜像分发;这是构建阶段最常见的泄密方式。

在 Box 中的位置

  • 构建实现位于 src/runtime/src/oci/build/,CLI 入口为 src/cli/src/commands/build.rs
  • Box 支持选定的 Dockerfile / Containerfile 子集,并使用内容寻址缓存。不被支持的指令在构建或运行前失败,而不是被静默忽略。
  • 构建产物随后可被 a3s-box run 使用。镜像准备仍由 Box 完成;执行隔离由 MicroVM 或 OCI Runtime 承担。

验证命令

a3s-box build -t local/app:dev .
a3s-box images
a3s-box run --rm local/app:dev

若当前目录没有 Dockerfile,build 应在产生镜像之前失败。这是「不支持的输入不得进入状态」这一原则在构建路径上的表现。

相关与易混

  • 相关:镜像与层镜像仓库 RegistryDocker 式 CLI
  • 易混:Dockerfile 不是 Compose 文件。前者描述如何生成一个镜像;后者描述如何同时运行多个已存在的镜像。EXPOSE 也不是端口发布。