【Docker Buildx】docker buildx本地构建多架构镜像,拉取镜像时的网络延迟问题(已解决)
问题描述
在WSL本地使用buildx
构建docker多架构镜像(linux/amd64
和linux/arm64
)时,拉取镜像遇到网络超时的问题:
$ docker buildx build --platform linux/amd64,linux/arm64 -t your-repo/image:1.0.0 --push .
[+] Building 30.0s (5/5) FINISHED docker-container:multi-platform-builder=> [internal] load build definition from Dockerfile 0.0s=> => transferring dockerfile: 1.06kB 0.0s=> ERROR [linux/amd64 internal] load metadata for docker.io/library/debian:bookworm-slim 30.0s=> CANCELED [linux/amd64 internal] load metadata for docker.io/library/rust:1.89.0-bookworm 30.0s=> CANCELED [linux/arm64 internal] load metadata for docker.io/library/debian:bookworm-slim 30.0s=> CANCELED [linux/arm64 internal] load metadata for docker.io/library/rust:1.89.0-bookworm 30.0s
------> [linux/amd64 internal] load metadata for docker.io/library/debian:bookworm-slim:
------
Dockerfile:18
--------------------16 | 17 | # ---------- Runtime ----------18 | >>> FROM debian:bookworm-slim19 | 20 | # 要求:基础镜像支持 /bin/bash
--------------------
ERROR: failed to build: failed to solve: debian:bookworm-slim: failed to resolve source metadata for docker.io/library/debian:bookworm-slim: failed to do request: Head "https://registry-1.docker.io/v2/library/debian/manifests/bookworm-slim": dial tcp 31.13.96.195:443: i/o timeout
解决方案
- 这种情况就是拉取docker hub镜像时的网络问题,我们可以通过挂代理的方式解决
- 我们通过
buildx
构建多架构镜像时,需要创建一个buildx
构建器,在创建buildx
构建器时,容器网络选择本机即可- 注意,windows需要开启代理,并允许局域网访问,例如:Clash设置
allow-lan:true
,同时WSL2网络需要开启mirrored
模式,参考:https://blog.east.monster/2022/10/05/clash-config-in-wsl/
- 注意,windows需要开启代理,并允许局域网访问,例如:Clash设置
创建Buildx构建器
- 创建buildx构建器来构建多架构镜像
docker buildx create --name multi-platform-builder \--platform linux/amd64,linux/arm64 \--driver docker-container \--driver-opt network=host \ # 该设置共享宿主机网络--driver-opt env.HTTP_PROXY="http://127.0.0.1:7890" \ # 设置拉取镜像时的代理--driver-opt env.HTTPS_PROXY="http://127.0.0.1:7890" \ # 设置拉取镜像时的代理--use
# 初始化并启用Buildx构建器
docker buildx inspect --bootstrap
📋 命令选项解析
选项/参数 | 含义与作用 | 补充说明 |
---|---|---|
docker buildx create | 创建一个新的 Buildx 构建器实例。 | Buildx 是 Docker 的扩展插件,用于扩展构建功能,尤其支持多平台构建。 |
--name multi-platform-builder | 指定新构建器的名称,这里命名为 multi-platform-builder 。 | 方便后续管理(如使用、检查、删除)时指定目标构建器。 |
--platform linux/amd64,linux/arm64 | 指定该构建器支持的目标平台架构,这里支持 AMD64 (常见于 Intel/AMD CPU) 和 ARM64 (常见于 Apple Silicon, AWS Graviton)。 | 使用此构建器时,可以构建这些指定平台的镜像。 |
--driver docker-container | 指定 Buildx 使用 docker-container 驱动。 | 此驱动会创建一个持久的、容器化的 BuildKit 环境,这是支持多平台构建和高级缓存等功能所必需的。 这是实现多平台构建的关键。 |
--driver-opt network=host | 设置驱动选项:网络模式。 此处 network=host 表示构建器容器将使用宿主机的网络栈。 | 构建器容器直接使用主机网络,避免 NAT 可能带来的问题,通常能提升网络性能,并更容易继承宿主机的网络配置(如代理)。 |
--driver-opt env.HTTP_PROXY="http://127.0.0.1:7890" | 设置驱动选项:环境变量。为构建器容器内部设置 HTTP_PROXY 环境变量,指定 HTTP 代理服务器地址。 | 此配置允许构建器容器通过你指定的 HTTP 代理(如 Clash, V2Ray 等常使用的 127.0.0.1:7890 )访问网络,用于加速镜像拉取或绕过网络限制。 |
--driver-opt env.HTTPS_PROXY="http://127.0.0.1:7890" | 设置驱动选项:环境变量。为构建器容器内部设置 HTTPS_PROXY 环境变量,指定 HTTPS 代理服务器地址。 | 同上,确保 HTTPS 流量(如与 Docker Hub 等安全镜像仓库通信)也通过代理进行。 |
--use | 创建完成后立即切换到新创建的 multi-platform-builder 构建器,并将其设置为当前活动的构建器。 | 后续的 docker buildx build 命令如果没有指定 --builder 参数,将默认使用此构建器。 |
💡 关于 --driver-opt
的补充
--driver-opt
用于向指定的驱动(这里是 docker-container
)传递额外的选项。
- 这些选项是针对驱动本身的,用于配置由驱动创建和管理的构建环境(即那个 BuildKit 容器)。
- 示例中的
network=host
和env.HTTP_PROXY...
等都是docker-container
驱动支持的选项。 - 你可以使用
docker buildx create --help
命令查看所有支持的驱动选项。
使用 Buildx Builder构建器
🛠️ 如何使用这个构建器
创建成功后,你就可以使用这个构建器来构建并推送多平台镜像了,命令基本形式如下:
docker buildx build \--platform linux/amd64,linux/arm64 \ # 指定要构建的平台,可与创建构建器时不同但需是其子集-t your-username/your-image:your-tag \ # 指定镜像名称和标签--push \ # 构建完成后自动将镜像推送到远程仓库(如 Docker Hub).
⚠️ 注意事项
- 代理可用性:确保
http://127.0.0.1:7890
确实是你可用的代理地址,并且该代理允许 Docker 容器的连接。如果代理需要认证,格式应为http://username:password@127.0.0.1:7890
。 - 环境变量大小写:有些程序可能也认小写的环境变量(如
http_proxy
),为保险起见,有时需要同时设置大小写形式。 network=host
的考虑:主机网络模式虽然能避免一些网络问题并可能提升性能,但放弃了容器网络的隔离性。 在大多数情况下,对于构建器容器这是可接受的。- 检查构建器:创建完成后,可以使用
docker buildx inspect --bootstrap
来检查构建器的详细状态和配置。 - 国内镜像源:如果你的网络环境在国内,即使使用代理,有时配置国内镜像源(在 Docker Daemon 配置中设置
registry-mirrors
)也能显著提升基础镜像的拉取速度。