最后更新于
最后更新于
我们知道使用镜像创建一个容器,该镜像必须与 Docker 宿主机系统架构一致,例如 Linux x86_64
架构的系统中只能使用 Linux x86_64
的镜像创建容器。
Windows、macOS 除外,其使用了 提供了多种架构支持,在 Windows、macOS 系统上 (x86_64) 可以运行 arm 等其他架构的镜像。
例如我们在 Linux x86_64
中构建一个 username/test
镜像。
构建镜像后推送到 Docker Hub,之后我们尝试在树莓派 Linux arm64v8
中使用这个镜像。
可以发现这个镜像根本获取不到。
要解决这个问题,通常采用的做法是通过镜像名区分不同系统架构的镜像,例如在 Linux x86_64
和 Linux arm64v8
分别构建 username/test
和 username/arm64v8-test
镜像。运行时使用对应架构的镜像即可。
这样做显得很繁琐,那么有没有一种方法让 Docker 引擎根据系统架构自动拉取对应的镜像呢?
我们发现在 Linux x86_64
和 Linux arm64v8
架构的计算机中分别使用 golang:alpine
镜像运行容器 $ docker run golang:alpine go version
时,容器能够正常的运行。
这是什么原因呢?
原因就是 golang:alpine
官方镜像有一个 。
当用户获取一个镜像时,Docker 引擎会首先查找该镜像是否有 manifest
列表,如果有的话 Docker 引擎会按照 Docker 运行环境(系统及架构)查找出对应镜像(例如 golang:alpine
)。如果没有的话会直接获取镜像(例如上例中我们构建的 username/test
)。
我们可以使用 $ docker manifest inspect golang:alpine
查看这个 manifest
列表的结构。
可以看出 manifest
列表中包含了不同系统架构所对应的镜像 digest
值,这样 Docker 就可以在不同的架构中使用相同的 manifest
(例如 golang:alpine
) 获取对应的镜像。
下面介绍如何使用 $ docker manifest
命令创建并推送 manifest
列表到 Docker Hub。
首先在 Linux x86_64
构建 username/x8664-test
镜像。并在 Linux arm64v8
中构建 username/arm64v8-test
镜像,构建好之后推送到 Docker Hub。
manifest
列表当要修改一个 manifest
列表时,可以加入 -a
或 --amend
参数。
manifest
列表这样就配置好了 manifest
列表。
manifest
列表manifest
列表最后我们可以将其推送到 Docker Hub。
我们在 Linux x86_64
Linux arm64v8
中分别执行 $ docker run -it --rm username/test
命令,发现可以正确的执行。
详细了解 manifest
可以阅读官方博客。
https://www.docker.com/blog/multi-arch-all-the-things/