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 引擎的访问权限,因为 此类访问可能允许他们执行供应链攻击。例如,build 和 将恶意镜像推送到组织的存储库或类似存储库中。
但是,某些合法用例要求容器能够访问 Docker Engine 套接字。例如,流行的 Testcontainers 框架有时会将 Docker Engine 套接字绑定到容器中,以 管理它们或执行测试后清理。同样,一些 Buildpack 框架 例如 Paketo,需要将 Docker 套接字绑定挂载到 器皿。
管理员可以选择将 ECI 配置为允许 bind 将 Docker Engine 套接字挂载到容器中,但以受控方式。
这可以通过 Docker Socket 挂载权限部分的admin-settings.json
文件。例如:
{
"configurationFileVersion": 2,
"enhancedContainerIsolation": {
"locked": true,
"value": true,
"dockerSocketMount": {
"imageList": {
"images": [
"docker.io/localstack/localstack:*",
"docker.io/testcontainers/ryuk:*",
"docker:cli"
],
"allowDerivedImages": true
},
"commandList": {
"type": "deny",
"commands": ["push"]
}
}
}
}
提示
现在,您还可以在 Docker Admin Console 中配置这些设置。
如上所示,有两种配置可用于绑定挂载 Docker
套接字到容器中:imageList
和commandList
.这些是
如下所述。
图片列表
这imageList
是允许绑定挂载
Docker 套接字。默认情况下,列表为空,不允许任何容器
bind-mount Docker 套接字。但是,管理员可以添加
images 添加到列表中,使用以下格式之一:
镜像参考格式 | 描述 |
---|---|
<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/localstack
或docker.io/testcontainers/ryuk
image(带有任何标签)或docker:cli
镜像,允许在启用 ECI 时绑定挂载 Docker 套接字。因此
以下工作:
$ docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker:cli sh
/ #
提示
限制您允许的镜像,如 建议中所述。
通常,使用标签通配符格式指定镜像会更容易,例如<image-name>:*
,因为imageList
不需要在新版本的
image 被使用。或者,您也可以使用不可变标签,例如: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>
则 tag作成功,但docker run
命令失败
因为不允许的镜像的镜像摘要与允许的
的。
派生镜像的 Docker 套接字挂载权限
如上一节所述,管理员可以配置容器列表
镜像,允许通过imageList
.
这适用于大多数情况,但并非总是如此,因为它需要预先了解
应允许挂载 Docker 套接字的镜像的名称。
一些容器工具,例如 Paketo buildpacks、
构建需要 Docker 套接字绑定挂载的临时本地镜像。由于
这些短暂的镜像是未知的,因此imageList
是不够的。
为了解决这个问题,从 Docker Desktop 版本 4.34 开始,Docker 套接字
挂载权限不仅适用于imageList
;他们
也适用于从imageList
.
也就是说,如果名为 “myLocalImage” 的本地镜像是从 “myBaseImage” 构建的
(即,具有FROM myBaseImage
),则如果 “myBaseImage” 位于
这imageList
,则 “myBaseImage” 和 “myLocalImage” 都可以挂载
Docker 套接字。
例如,要使 Paketo buildpack 能够与 Docker Desktop 和 ECI 一起使用,
只需将以下镜像添加到imageList
:
"imageList": {
"images": [
"paketobuildpacks/builder:base"
],
"allowDerivedImages": true
}
当 buildpack 运行时,它将创建一个派生自paketobuildpacks/builder:base
并将 Docker 套接字挂载到它上面。ECI 将
允许这样做,因为它会注意到短暂镜像是从
允许的图片。
默认情况下,该行为处于禁用状态,并且必须通过设置"allowDerivedImages": true
如上所示。一般来说,建议
除非您知道此设置是必需的,否则请禁用此设置。
一些注意事项:
设置
"allowedDerivedImages" :true
会影响 容器最多额外增加 1 秒,因为 Docker Desktop 需要执行 对容器镜像进行更多检查。这
allowDerivedImages
设置仅适用于仅本地镜像 允许的镜像。也就是说,派生的镜像不能存在于远程 repository 中,因为如果是这样,您只需在imageList
.要使派生镜像检查正常工作,父镜像(即
imageList
) 必须存在于本地(即,必须已被显式拉取 来自存储库)。这通常不是问题,因为需要这个的工具 功能(例如 Paketo buildpacks)将对父镜像进行预拉取。仅适用于 Docker Desktop 版本 4.34 和 4.35:该
allowDerivedImages
设置 适用于imageList
使用显式标记指定(例如<name>:<tag>
).它不适用于使用标记通配符指定的镜像 (例如,<name>:*
) 中。在 Docker Desktop 4.36 和 稍后,此警告不再适用,这意味着allowDerivedImages
设置适用于指定且带或不带通配符标签的镜像。这 可以更轻松地管理 ECI Docker 套接字镜像列表。
允许所有容器挂载 Docker 套接字
在 Docker Desktop 版本 4.36 及更高版本中,可以配置镜像
list 以允许任何容器挂载 Docker 套接字。您可以通过向"*"
imageList
:
"imageList": {
"images": [
"*"
]
}
这会告诉 Docker Desktop 允许所有容器挂载 Docker 套接字 这增加了灵活性,但降低了安全性。它还改进了容器 使用增强型容器隔离时的启动时间。
建议您仅在明确列出 允许的容器镜像不够灵活。
命令列表
除了imageList
在前面的章节中,ECI 可以进一步
限制容器可以通过绑定挂载的 Docker 发出的命令
插座。这是通过 Docker 套接字挂载权限完成的commandList
和
充当imageList
(即,像
第二道防线)。
例如,假设imageList
配置为允许镜像docker:cli
自
挂载 Docker 套接字,并使用它启动一个容器:
$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock sh
/ #
默认情况下,这允许容器通过该 Docker 发出任何命令 套接字(例如,构建镜像并将其推送到组织的存储库),该 通常不可取。
为了提高安全性,commandList
可以配置为限制
容器内部的进程可以在 Bind-mounted
Docker 套接字。这commandList
可以配置为 “deny” 列表(默认)或
一个 “允许” 列表,具体取决于您的偏好。
列表中的每个命令都由其名称指定,如docker --help
(例如,“ps”、“build”、“pull”、“push” 等)此外,以下内容
命令通配符可以阻止整组命令:
命令通配符 | 描述 |
---|---|
“容器*” | 指所有 “docker container ...”命令 |
“镜像*” | 指所有 “docker image ...”命令 |
“卷*” | 指所有 “docker volume ...”命令 |
“网络 * ” | 指所有 “docker network ...”命令 |
“构建*” | 指所有 “docker build ...”命令 |
“系统*” | 指所有 “docker system ...”命令 |
例如,以下配置会阻止build
和push
命令
在 Docker 套接字上:
"commandList": {
"type": "deny",
"commands": ["build", "push"]
}
因此,如果在容器内,您对 bind 挂载的 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 http://localhost/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 套接字通常会创建/运行/删除容器, 卷和网络,但通常不会构建镜像或将它们推送到 repositories (尽管有些可能会合法地这样做)。允许哪些命令或 阻止取决于用例。- 请注意,容器通过 bind-mounted Docker 套接字也将在增强的容器隔离(即 生成的容器使用 Linux 用户命名空间的敏感系统 电话经过审查,等等。
注意事项和限制
当 Docker Desktop 重新启动时,允许的镜像可能会 挂载 Docker 套接字时,会意外地阻止这样做。这可以 当远程存储库中的镜像摘要发生更改时(例如,一个 “:latest” 镜像已更新)和该镜像的本地副本(例如,来自 事先
docker pull
) 不再与远程存储库中的摘要匹配。在 在这种情况下,请删除本地镜像并再次拉取它(例如docker rm <image>
和docker pull <image>
).不允许在容器上使用 Docker 套接字绑定挂载 仅限本地的镜像(即不在注册表中的镜像),除非它们派生自允许的镜像,或者您允许所有容器挂载 Docker 套接字。 这是因为 Docker Desktop 从以下位置提取允许的镜像的摘要 注册表,然后使用它与 镜像。
这
commandList
配置适用于所有允许 bind-mount Docker 套接字。因此,不能根据 容器。以下命令在
commandList
:
不支持的命令 | 描述 |
---|---|
compose | Docker Compose |
dev | 开发环境 |
extension | 管理 Docker 扩展 |
feedback | 向 Docker 发送反馈 |
init | 创建与 Docker 相关的启动文件 |
manifest | 管理 Docker 镜像清单 |
plugin | 管理插件 |
sbom | 查看软件物料清单 (SBOM) |
scout | Docker Scout |
trust | 管理对 Docker 镜像的信任 |
注意
运行 “true” 时,Docker 套接字挂载权限不适用 Docker-in-Docker(即,在容器内运行 Docker 引擎时)。在 在这种情况下,没有将主机的 Docker 套接字绑定到 容器,因此容器没有利用该配置的风险 以及主机的 Docker Engine 的凭证来执行恶意活动。 增强的容器隔离能够安全地运行 Docker-in-Docker, 无需在 Docker Desktop 中为外部容器提供真正的 root 权限 虚拟机。