別再寫丑陋的 Docker Build 命令了!試試這個優雅方案!
在日常 DevOps 工作中,很多人都曾被繁瑣的 docker build 命令折磨過:
- 一堆 --build-arg、-t、-f 參數要記;
- 每次構建多平臺鏡像時要不停地查文檔;
- 管理單體倉庫(mono repo)時,還要寫一堆重復命令來構建前后端鏡像。
長此以往,你的終端里充滿了又臭又長的命令行記錄,既不美觀,也不利于版本管理。
而現在,Docker 官方終于給出了答案——Docker Bake。 這是 Docker 在 Desktop 4.38 中正式發布的構建編排工具,它把復雜的構建邏輯抽象為配置文件,只需一個命令就能完成以前需要數條命令才能搞定的工作。
這篇文章就帶你從頭到尾深入理解 為什么 Docker Bake 是更聰明的構建與管理 Docker 鏡像的方式。
為什么不該繼續手寫 docker build 命令?
我們先來看看傳統方式下,構建兩個應用鏡像需要的命令。假設項目目錄結構如下:
/project-root
├── frontend/
│ └── frontend.Dockerfile
└── backend/
└── backend.Dockerfile在這種情況下,想要分別構建前端和后端鏡像,你需要執行:
# 構建前端鏡像
docker build --build-arg NODE_VERSION=20 -t \
366140438193.dkr.ecr.ap-south-1.amazonaws.com/frontend:latest \
-f frontend/frontend.Dockerfile frontend
# 構建后端鏡像
docker build --build-arg GO_VERSION=1.21 -t \
366140438193.dkr.ecr.ap-south-1.amazonaws.com/backend:latest \
-f backend/backend.Dockerfile backend
# 推送到 ECR
docker push 366140438193.dkr.ecr.ap-south-1.amazonaws.com/frontend:latest
docker push 366140438193.dkr.ecr.ap-south-1.amazonaws.com/backend:latest光是這兩個服務就要寫 4 條命令,而且充滿各種參數,一旦項目規模更大,這種方式幾乎不可維護。
更糟糕的是,這些命令通常不會寫進 Git 倉庫,而是散落在團隊成員的終端歷史中。對新人來說,學習成本極高。
Docker Bake 登場
Docker Bake 的核心思想是:用配置文件(HCL/YAML/JSON)來定義鏡像構建流程,而不是直接寫命令。
這樣,你的構建配置就像 Terraform 或 docker-compose.yml 一樣:
- 可讀性更好
- 可版本化管理
- 支持復用與繼承
只要一行命令,就能完成所有構建:
docker buildx bake一個簡單示例
我們在項目根目錄下新建文件 /project-root/docker-bake.hcl,寫入如下內容:
# docker-bake.hcl
group "default" {
targets = ["frontend", "backend"]
}
target "frontend" {
context = "./frontend"
dockerfile = "frontend.Dockerfile"
args = {
NODE_VERSION = "20"
}
tags = ["366140438193.dkr.ecr.ap-south-1.amazonaws.com/frontend:latest"]
}
target "backend" {
context = "./backend"
dockerfile = "backend.Dockerfile"
args = {
GO_VERSION = "1.21"
}
tags = ["366140438193.dkr.ecr.ap-south-1.amazonaws.com/backend:latest"]
}然后直接運行:
docker buildx bake此時,前端和后端鏡像都會被自動構建完成。若想直接推送到遠程倉庫,只需加上 --push:
docker buildx bake --push是不是優雅很多??
更復雜場景下的 Bake 用法
映射傳統 docker build 命令
假設你平時寫的命令是這樣的:
docker build \
-f Dockerfile \
-t myapp:latest \
--build-arg foo=bar \
--no-cache \
--platform linux/amd64,linux/arm64 \
.在 docker-bake.hcl 中可以這樣表示:
target "myapp" {
context = "."
dockerfile = "Dockerfile"
tags = ["myapp:latest"]
args = {
foo = "bar"
}
no-cache = true
platforms = ["linux/amd64", "linux/arm64"]
}運行時只需:
docker buildx bake myapp目標分組與多服務構建
在實際項目(比如 com/icoderoad/devops/mono-repo)中,可能同時有 webapp、api、tests 三個服務。我們可以這樣寫:
group "all" {
targets = ["webapp", "api", "tests"]
}
target "webapp" {
dockerfile = "webapp.Dockerfile"
tags = ["docker.io/username/webapp:latest"]
context = "./webapp"
}
target "api" {
dockerfile = "api.Dockerfile"
tags = ["docker.io/username/api:latest"]
context = "./api"
}
target "tests" {
dockerfile = "tests.Dockerfile"
contexts = {
webapp = "target:webapp",
api = "target:api"
}
output = ["type=local,dest=build/tests"]
context = "."
}然后執行:
docker buildx bake all即可一次性構建全部目標。
繼承與復用
Bake 支持 繼承配置,比如:
target "common" {
context = "."
platforms = ["linux/amd64", "linux/arm64"]
}
target "backend" {
inherits = ["common"]
dockerfile = "backend.Dockerfile"
args = {
GO_VERSION = "1.21"
}
}
target "frontend" {
inherits = ["common"]
dockerfile = "frontend.Dockerfile"
args = {
NODE_VERSION = "20"
}
}這樣就不用在每個 target 中重復配置平臺信息。
使用變量(像 Terraform 一樣)
variable "NODE_VERSION" {
default = "20"
}
variable "tag" {
default = "latest"
}
target "frontend" {
context = "."
dockerfile = "frontend.Dockerfile"
args = {
NODE_VERSION = NODE_VERSION
}
tags = ["myapp-frontend:${tag}"]
}運行時通過 --print 可以查看展開后的最終配置:
docker buildx bake --print條件判斷與函數
Bake 甚至支持類似編程語言的表達式:
variable "FOO" {
default = 3
}
target "app" {
args = {
v1 = FOO > 5 ? "higher" : "lower"
v2 = timestamp()
}
}還能自定義函數生成鏡像標簽,非常靈活。
遠程 Bake 文件與多格式支持
你可以直接從 Git 倉庫或 URL 使用 Bake 配置:
docker buildx bake --file https://raw.githubusercontent.com/icoderoad/project/docker-bake.hcl配置文件支持 HCL、YAML、JSON 格式,不局限于 .hcl。
總結
過去,Docker 構建鏡像的方式像是在寫“咒語”,記不住就只能復制粘貼。而 Docker Bake 把一切變得清晰可控:
- 構建邏輯配置化、版本可控
- 支持復用、繼承和變量
- 一條命令即可完成多服務、多平臺鏡像構建
對于 DevOps 工程師 來說,這不僅提高了效率,也讓團隊協作更順暢。
未來無論是單體倉庫還是大型分布式項目,Docker Bake 都將成為標準的鏡像構建工具。與其繼續苦記繁瑣命令,不如立刻把你的構建腳本遷移到 Bake —— 你會發現,原來構建 Docker 鏡像也能如此優雅。






























