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-sharesCPU 共享(相對權重)
--cpuset-cpus允許執行的 CPU (0-3, 0,1)
--cpuset-mems允許執行的記憶體(0-3,0,1)
--disable-content-trusttrue跳過映象驗證
-f, --fileDockerfile 的名稱(預設為 PATH/Dockerfile
--force-rm始終刪除中間容器
--iidfile將映象 ID 寫入檔案
--isolation容器隔離技術
--label為映象設定元資料
-m, --memory記憶體限制
--memory-swap交換限制等於記憶體加交換:-1 表示啟用無限制交換
--networkAPI 1.25+ 在構建期間為 RUN 指令設定網路模式
--no-cache構建映象時不使用快取
--platformAPI 1.38+ 如果伺服器支援多平臺,則設定平臺
--pull始終嘗試拉取更新版本的映象
-q, --quiet抑制構建輸出並在成功時列印映象 ID
--rmtrue成功構建後刪除中間容器
--security-opt安全選項
--shm-size/dev/shm 的大小
--squashAPI 1.25+ 實驗性(守護程式)將新構建的層壓縮為單個新層
-t, --tag名稱,可選地帶一個 name:tag 格式的標籤
--target設定要構建的目標構建階段。
--ulimitUlimit 選項

示例

為容器指定隔離技術 (--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.txtregistry://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