docker build (舊版構建器)
描述 | 從 Dockerfile 構建映象 |
---|---|
用法 | docker image build [OPTIONS] PATH | URL | - |
別名 | docker image build docker build docker builder build |
描述
重要本頁指的是
docker build
的**舊版實現**,使用舊版(pre-BuildKit)構建後端。此配置僅在構建 Windows 容器時相關。有關使用 Buildx 的預設
docker build
的資訊,請參閱docker buildx build
。
使用舊版構建器構建時,映象是透過執行一系列 commit 從 Dockerfile 建立的。與使用 BuildKit 相比,此過程效率低下且速度慢,因此除了構建 Windows 容器之外,此構建策略已棄用。它仍然適用於構建 Windows 容器,因為 BuildKit 尚未完全支援 Windows 的所有功能。
除非滿足以下條件,否則透過 docker build
呼叫的構建預設使用 Buildx(和 BuildKit):
- 您正在 Windows 容器模式下執行 Docker Engine。
- 您透過設定環境變數
DOCKER_BUILDKIT=0
明確選擇不使用 BuildKit。
本頁上的描述僅涵蓋舊版構建器獨有的資訊,以及舊版構建器與 BuildKit 行為不同的情況。有關舊版構建器和 BuildKit 之間通用功能和標誌(例如 --tag
和 --target
)的資訊,請參閱 docker buildx build
的文件。
使用舊版構建器構建上下文
構建上下文是您在呼叫構建命令時傳遞的位置引數。在以下示例中,上下文是 .
,表示當前工作目錄。
$ docker build .
使用舊版構建器時,構建上下文會完整地傳送到守護程式。使用 BuildKit 時,只傳輸構建中使用的檔案。舊版構建器不會事先計算需要哪些檔案。這意味著對於具有大上下文的構建,上下文傳輸可能需要很長時間,即使您只使用上下文中包含的檔案子集。
因此,使用舊版構建器時,仔細考慮您在指定上下文中包含哪些檔案尤為重要。使用 .dockerignore
檔案可將構建中不需要的檔案和目錄排除在構建上下文之外,使其不被髮送。
訪問構建上下文之外的路徑
如果您嘗試在 Dockerfile 中使用相對路徑訪問構建上下文之外的檔案,舊版構建器將報錯。
FROM alpine
COPY ../../some-dir .
$ docker build .
...
Step 2/2 : COPY ../../some-dir .
COPY failed: forbidden path outside the build context: ../../some-dir ()
另一方面,BuildKit 會剝離超出構建上下文的開頭相對路徑。以上一個示例為例,路徑 COPY ../../some-dir .
在 BuildKit 中會評估為 COPY some-dir .
。
選項
選項 | 預設值 | 描述 |
---|---|---|
--add-host | 新增自定義主機到 IP 對映 (host:ip ) | |
--build-arg | 設定構建時變數 | |
--cache-from | 要考慮作為快取源的映象 | |
--cgroup-parent | 設定構建期間 RUN 指令的父 cgroup | |
--compress | 使用 gzip 壓縮構建上下文 | |
--cpu-period | 限制 CPU CFS(完全公平排程器)週期 | |
--cpu-quota | 限制 CPU CFS(完全公平排程器)配額 | |
-c, --cpu-shares | CPU 共享(相對權重) | |
--cpuset-cpus | 允許執行的 CPU (0-3, 0,1) | |
--cpuset-mems | 允許執行的記憶體(0-3,0,1) | |
--disable-content-trust | true | 跳過映象驗證 |
-f, --file | Dockerfile 的名稱(預設為 PATH/Dockerfile ) | |
--force-rm | 始終刪除中間容器 | |
--iidfile | 將映象 ID 寫入檔案 | |
--isolation | 容器隔離技術 | |
--label | 為映象設定元資料 | |
-m, --memory | 記憶體限制 | |
--memory-swap | 交換限制等於記憶體加交換:-1 表示啟用無限制交換 | |
--network | API 1.25+ 在構建期間為 RUN 指令設定網路模式 | |
--no-cache | 構建映象時不使用快取 | |
--platform | API 1.38+ 如果伺服器支援多平臺,則設定平臺 | |
--pull | 始終嘗試拉取更新版本的映象 | |
-q, --quiet | 抑制構建輸出並在成功時列印映象 ID | |
--rm | true | 成功構建後刪除中間容器 |
--security-opt | 安全選項 | |
--shm-size | /dev/shm 的大小 | |
--squash | API 1.25+ 實驗性(守護程式)將新構建的層壓縮為單個新層 | |
-t, --tag | 名稱,可選地帶一個 name:tag 格式的標籤 | |
--target | 設定要構建的目標構建階段。 | |
--ulimit | Ulimit 選項 |
示例
為容器指定隔離技術 (--isolation)
此選項在 Windows 上執行 Docker 容器時非常有用。--isolation=
選項設定容器的隔離技術。在 Linux 上,唯一支援的是使用 Linux 名稱空間的 default
選項。在 Microsoft Windows 上,您可以指定以下值:
值 | 描述 |
---|---|
default | 使用 Docker 守護程式的 --exec-opt 指定的值。如果 daemon 未指定隔離技術,Microsoft Windows 將使用 process 作為其預設值。 |
程序 | 僅名稱空間隔離。 |
hyperv | 基於 Hyper-V 虛擬機器監控程式分割槽的隔離。 |
可選安全選項 (--security-opt)
此標誌僅在 Windows 上執行的守護程式上受支援,並且僅支援 credentialspec
選項。credentialspec
必須是 file://spec.txt
或 registry://keyname
格式。
壓縮映象層 (--squash) (實驗性)
概述
注意
--squash
選項是一項實驗性功能,不應視為穩定。
映象構建完成後,此標誌將新層壓縮成一個新映象,該映象僅包含一個新層。壓縮不會銷燬任何現有映象,而是建立一個包含壓縮層內容的新映象。這實際上使所有 Dockerfile
命令看起來都只建立了一個層。--squash
標誌保留了構建快取。
如果 Dockerfile 生成了多個修改相同檔案的層,例如在一個步驟中建立檔案而在另一個步驟中刪除檔案,則壓縮層可能很有益。對於其他用例,壓縮映象實際上可能對效能產生負面影響。拉取由多個層組成的映象時,守護程式可以並行拉取層,並允許在映象之間共享層(節省空間)。
對於大多數用例,多階段構建是更好的選擇,因為它們可以對構建進行更精細的控制,並且可以利用構建器中未來的最佳化。有關更多資訊,請參閱多階段構建部分。
已知限制
--squash
選項存在一些已知限制:
- 壓縮層時,生成的映象無法利用與其他映象的層共享,並且可能佔用更多空間。基礎映象的共享仍然受支援。
- 使用此選項時,由於儲存了兩份映象副本(一份用於構建快取,所有快取層完好無損;一份用於壓縮版本),您可能會看到使用的空間顯著增加。
- 雖然壓縮層可能會生成更小的映象,但它可能對效能產生負面影響,因為單個層需要更長時間才能解壓縮,並且無法並行下載單個層。
- 當嘗試壓縮一個不對檔案系統進行更改的映象(例如,Dockerfile 只包含
ENV
指令)時,壓縮步驟將失敗(請參閱 問題 #33823)。
先決條件
本頁面上的示例使用了 Docker 23.03 中的實驗模式。
您可以透過在啟動 Docker 守護程式時使用 --experimental
標誌,或在 daemon.json
配置檔案中設定 experimental: true
來啟用實驗模式。
預設情況下,實驗模式是停用的。要檢視 Docker 守護程式的當前配置,請使用 docker version
命令並檢查 Engine
部分中的 Experimental
行。
Client: Docker Engine - Community
Version: 23.0.3
API version: 1.42
Go version: go1.19.7
Git commit: 3e7cbfd
Built: Tue Apr 4 22:05:41 2023
OS/Arch: darwin/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 23.0.3
API version: 1.42 (minimum version 1.12)
Go version: go1.19.7
Git commit: 59118bf
Built: Tue Apr 4 22:05:41 2023
OS/Arch: linux/amd64
Experimental: true
[...]
使用 --squash
標誌構建映象
以下是使用 --squash
標誌構建的示例。下面是 Dockerfile
:
FROM busybox
RUN echo hello > /hello
RUN echo world >> /hello
RUN touch remove_me /remove_me
ENV HELLO=world
RUN rm /remove_me
接下來,使用 --squash
標誌構建名為 test
的映象。
$ docker build --squash -t test .
構建完成後,歷史記錄如下所示。歷史記錄可能顯示某層的名稱為 <missing>
,並有一個 COMMENT 為 merge
的新層。
$ docker history test
IMAGE CREATED CREATED BY SIZE COMMENT
4e10cb5b4cac 3 seconds ago 12 B merge sha256:88a7b0112a41826885df0e7072698006ee8f621c6ab99fca7fe9151d7b599702 to sha256:47bcc53f74dc94b1920f0b34f6036096526296767650f223433fe65c35f149eb
<missing> 5 minutes ago /bin/sh -c rm /remove_me 0 B
<missing> 5 minutes ago /bin/sh -c #(nop) ENV HELLO=world 0 B
<missing> 5 minutes ago /bin/sh -c touch remove_me /remove_me 0 B
<missing> 5 minutes ago /bin/sh -c echo world >> /hello 0 B
<missing> 6 minutes ago /bin/sh -c echo hello > /hello 0 B
<missing> 7 weeks ago /bin/sh -c #(nop) CMD ["sh"] 0 B
<missing> 7 weeks ago /bin/sh -c #(nop) ADD file:47ca6e777c36a4cfff 1.113 MB
測試映象,檢查 /remove_me
是否已刪除,確保 hello\nworld
在 /hello
中,確保 HELLO
環境變數的值為 world
。