Dockerfile/BuildKit vs CNB: 为什么会有 Cloud Native Buildpacks
问题从哪来 构建容器镜像,最常见的做法是写一个 Dockerfile(或 Containerfile),交给 BuildKit、Buildah、Kaniko 之类的构建器执行。Cloud Native Buildpacks(CNB)则不需要 Dockerfile:把源码或 jar 交给 builder,自动产出 OCI 镜像。 既然 Dockerfile 已经能构建任意镜像,为什么还会出现 CNB?它解决的是 Dockerfile 解决不了的问题,还是别的问题?本文把这几个问题放在一起整理。CNB 的概念与 Paketo 用法见 CNB: Cloud Native Buildpacks 与 Paketo,Dockerfile 写法见 Containerfile。 先说结论:CNB 主要解决的不是「单个镜像能不能构建出来」,而是「几百上千个应用的镜像由谁来写、怎么统一、基础镜像出漏洞后怎么批量修」。这是组织规模上的问题,不是 Dockerfile 语法能力上的问题。 BuildKit 是什么 BuildKit 是 Moby 项目下的构建引擎,Docker Engine 23.0 起在 Linux 上成为 docker build 的默认后端,docker buildx 也基于它。 一个常被忽略的点:BuildKit 本身并不依赖 Dockerfile。它的结构分两层: 前端(frontend):把某种构建描述翻译成 LLB(Low-Level Build definition,一种描述构建步骤的有向无环图)。Dockerfile 只是其中一个前端,Dockerfile 首行的 # syntax=docker/dockerfile:1 指定的就是前端镜像。 求解器(solver):执行 LLB,负责并行、缓存、导出镜像。 flowchart LR DF[Dockerfile] OTHER[其他前端Dagger / Railpack 等] FE[Frontend] LLB[LLB DAG] SOLVER[BuildKit Solver并行 + 缓存] OUT[OCI 镜像 / 本地文件] DF --> FE OTHER --> LLB FE --> LLB --> SOLVER --> OUT 所以更准确的说法是:「Dockerfile 是一种构建描述语言,BuildKit 是执行引擎」。Dagger 的引擎、Railway 的 Railpack 等工具都直接生成 LLB,不写 Dockerfile 也能用 BuildKit。 ...