高階配置選項

注意

此功能適用於 Mac、Linux 和 Windows(Hyper-V)上的 Docker Desktop 4.27(及更高版本)。對於使用 WSL 2 的 Windows,此功能需要 Docker Desktop 4.28 及更高版本。

本頁面介紹了啟用 ECI 後,ECI 的可選高階配置。

Docker 套接字掛載許可權

預設情況下,啟用 ECI 後,Docker Desktop 不允許將 Docker Engine 套接字繫結掛載到容器中。

$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock docker:cli
docker: Error response from daemon: enhanced container isolation: docker socket mount denied for container with image "docker.io/library/docker"; image is not in the allowed list; if you wish to allow it, configure the docker socket image list in the Docker Desktop settings.

這可以防止惡意容器訪問 Docker Engine,因為這種訪問可能會使它們執行供應鏈攻擊(例如,將惡意映象構建和推送至組織的儲存庫)或類似攻擊。

但是,某些合法用例需要容器訪問 Docker Engine 套接字。例如,流行的 Testcontainers 框架有時會將 Docker Engine 套接字繫結掛載到容器中以管理它們或執行測試後清理。

從 Docker Desktop 4.27 開始,管理員可以選擇配置 ECI 以允許將 Docker Engine 套接字繫結掛載到容器中,但在受控方式下。

這可以透過 admin-settings.json 檔案完成,如 設定管理 中所述。例如

{
  "configurationFileVersion": 2,
  "enhancedContainerIsolation": {
    "locked": true,
    "value": true,
    "dockerSocketMount": {
      "imageList": {
        "images": [
          "docker.io/localstack/localstack:*",
          "docker.io/testcontainers/ryuk:*",
          "docker:cli"
        ]
      },
      "commandList": {
        "type": "deny",
        "commands": ["push"]
      }
    }
  }
}

如上所示,有兩種配置可用於將 Docker 套接字繫結掛載到容器中:imageListcommandList。這些將在下面介紹。

映象列表

imageList 是允許繫結掛載 Docker 套接字的容器映象列表。預設情況下,該列表為空(即,啟用 ECI 後,不允許任何容器繫結掛載 Docker 套接字)。但是,管理員可以使用以下兩種格式將映象新增到該列表中。

映象引用格式描述
<image_name>[:<tag>]映象名稱,帶有可選的標籤。如果省略標籤,則使用 :latest 標籤。如果標籤是萬用字元 *,則表示“該映象的任何標籤”。
<image_name>@<digest>映象名稱,帶有特定的儲存庫摘要(例如,由 docker buildx imagetools inspect <image> 報告)。這意味著只有與該名稱和摘要匹配的映象才被允許。

映象名稱遵循標準約定,因此它可以指向任何登錄檔和儲存庫。

在上面的示例中,映象列表配置了三個映象

"imageList": {
  "images": [
    "docker.io/localstack/localstack:*",
    "docker.io/testcontainers/ryuk:*",
    "docker:cli"
  ]
}

這意味著使用 docker.io/localstack/localstackdocker.io/testcontainers/ryuk 映象(帶任何標籤)或 docker:cli 映象的容器在啟用 ECI 後被允許繫結掛載 Docker 套接字。因此,以下操作有效

$ docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker:cli sh
/ #

提示

限制您允許的映象,如下面 建議 中所述。

通常,使用標籤萬用字元格式(例如,<image-name>:*)指定映象更輕鬆,因為這樣 imageList 就不需要在使用新版本的映象時更新。或者,您可以使用不可變標籤(例如,:latest),但它並不總是像萬用字元那樣有效,因為例如,Testcontainers 使用的是映象的特定版本,並不一定是最新版本。

啟用 ECI 後,Docker Desktop 會定期從相應的登錄檔下載允許映象的映象摘要並將其儲存在記憶體中。然後,當使用 Docker 套接字繫結掛載啟動容器時,Docker Desktop 會檢查容器的映象摘要是否與允許的摘要之一匹配。如果匹配,則允許容器啟動,否則將被阻止。

請注意,由於前面段落中提到的摘要比較,無法透過將不允許的映象重新標記為允許的映象的名稱來繞過 Docker 套接字掛載許可權。換句話說,如果使用者執行以下操作

$ docker image rm <allowed_image>
$ docker tag <disallowed_image> <allowed_image>
$ docker run -v /var/run/docker.sock:/var/run/docker.sock <allowed_image>

那麼標記操作將成功,但 docker run 命令會失敗,因為不允許的映象的映象摘要將與儲存庫中允許的映象的摘要不匹配。

命令列表

commandList 限制了容器在啟用 ECI 時透過繫結掛載的 Docker 套接字發出的 Docker 命令。它充當 imageList 的補充安全機制(即,像第二道防線)。

例如,假設 imageList 配置為允許映象 docker:cli 掛載 Docker 套接字,並且使用它啟動了一個容器

$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock sh
/ #

預設情況下,這允許容器透過該 Docker 套接字發出任何命令(例如,將映象構建並推送至組織的儲存庫),這通常不可取。

為了提高安全性,可以配置 commandList 來限制容器內的程序可以在繫結掛載的 Docker 套接字上發出的命令。commandList 可以配置為“拒絕”列表(預設)或“允許”列表,具體取決於您的偏好。

列表中的每個命令都由其名稱指定,如 docker --help 所報告(例如,“ps”、“build”、“pull”、“push”等)。此外,以下命令萬用字元允許阻止一組命令

命令萬用字元描述
"container*"指所有“docker container …” 命令
"image*"指所有“docker image …” 命令
"volume*"指所有“docker volume …” 命令
"network*"指所有“docker network …” 命令
"build*"指所有“docker build …” 命令
"system*"指所有“docker system …” 命令

例如,以下配置會阻止 Docker 套接字上的 buildpush 命令

"commandList": {
  "type": "deny",
  "commands": ["build", "push"]
}

因此,如果在容器內部,您在繫結掛載的 Docker 套接字上發出這兩個命令中的任何一個,它們將被阻止。

/ # docker push myimage
Error response from daemon: enhanced container isolation: docker command "/v1.43/images/myimage/push?tag=latest" is blocked; if you wish to allow it, configure the docker socket command list in the Docker Desktop settings or admin-settings.

同樣地

/ # curl --unix-socket /var/run/docker.sock -XPOST https:///v1.43/images/myimage/push?tag=latest
Error response from daemon: enhanced container isolation: docker command "/v1.43/images/myimage/push?tag=latest" is blocked; if you wish to allow it, configure the docker socket command list in the Docker Desktop settings or admin-settings.

請注意,如果 commandList 配置為“允許”列表,那麼效果將相反:只有列出的命令才被允許。是否將列表配置為允許列表或拒絕列表取決於用例。

建議

  • 限制允許繫結掛載 Docker 套接字的容器映象列表(即,imageList)。通常,只允許絕對必要且您信任的映象。

  • 如果可能,在 imageList 中使用標籤萬用字元格式(例如,<image_name>:*),因為這樣可以消除由於映象標籤更改而需要更新 admin-settings.json 檔案的需要。

  • commandList 中,阻止您不希望容器執行的命令。例如,對於本地測試(例如,Testcontainers),將 Docker 套接字繫結掛載的容器通常會建立/執行/刪除容器、卷和網路,但通常不會構建映象或將其推送至儲存庫(儘管有些可能合法地這樣做)。允許或阻止哪些命令取決於用例。

    • 請注意,容器透過繫結掛載的 Docker 套接字發出的所有“docker”命令也將以增強型容器隔離的方式執行(即,生成的容器使用 Linux 使用者名稱空間,敏感系統呼叫會經過驗證,等等)。

注意事項和限制

  • 重新啟動 Docker Desktop 後,允許掛載 Docker 套接字的映象可能會意外地被阻止這樣做。當映象摘要在遠端儲存庫中發生變化時(例如,“:latest”映象已更新)並且該映象的本地副本(例如,來自先前的 docker pull)不再與遠端儲存庫中的摘要匹配時,可能會發生這種情況。在這種情況下,請刪除本地映象並再次拉取它(例如,docker rm <image>docker pull <image>)。

  • 無法允許對不在登錄檔中的映象進行 Docker 套接字繫結掛載(例如,本地構建但尚未推送到登錄檔的映象)。這是因為 Docker Desktop 從登錄檔中拉取允許映象的摘要,然後使用它與映象的本地副本進行比較。

  • commandList 配置適用於所有允許繫結掛載 Docker 套接字的容器。因此,它不能針對每個容器進行不同的配置。

  • 以下命令在 commandList 中尚不支援

不支援的命令描述
composeDocker compose
devDocker 開發環境
extension管理 Docker 擴充套件
feedback向 Docker 傳送反饋
init建立與 Docker 相關的入門檔案
manifest管理 Docker 映象清單
plugins管理外掛
sbom檢視軟體物料清單 (SBOM)
scanDocker Scan
scoutDocker Scout
信任管理 Docker 映象的信任

注意

當執行“真正的”Docker-in-Docker(即在容器內執行 Docker 引擎)時,Docker 套接字掛載許可權不適用。在這種情況下,不會將宿主機 Docker 套接字繫結掛載到容器中,因此容器不會利用宿主機 Docker 引擎的配置和憑據來執行惡意活動。增強型容器隔離功能能夠安全地執行 Docker-in-Docker,而無需在 Docker Desktop VM 中為外部容器提供真正的 root 許可權。