先说结论:在M1芯片的Mac电脑上,使用docker pull拉取镜像时,会默认拉取arm架构的镜像,而不是x86或amd64架构的镜像。
而不同架构的镜像,在其他架构平台上是无法运行的。
背景
最近,公司在开发一个AI问答机器人,技术选型Milvus作为向量数据库。Milvus的搭建有详细的官方文档,使用Docker Compose就能快速地部署。
我把这个任务交给了另一位同事来负责,并且我多提了一个要求,要把使用的外网Docker镜像先保存到Harbor私有仓库,然后使用Harbor中的镜像来启动容器。
这是一个企业使用Docker镜像的最佳实践,可以避免无法预知的网络问题,并提升下载镜像的速度和稳定性。
然而,当启动Docker Compose时,遇到了错误,容器启动失败。
我们的操作是这样的:
步骤一:下载公开镜像。比如,需要etcd镜像:
docker pull quay.io/coreos/etcd:v3.5.5
步骤二:将公开镜像重新打tag:
docker tag quay.io/coreos/etcd:v3.5.5 192.168.100.100/coreos/etcd:v3.5.5
步骤三:将镜像推送到Harbor
docker push 192.168.100.100/coreos/etcd:v3.5.5
步骤四:下载Milvus提供的Docker Compose的YAML文件,并在Linux服务器启动Milvus
docker-compose up -d
经排查,问题其实出现在第一步,从一开始就错了。
同事的电脑是M1芯片的Mac。他在Mac上用docker pull命令拉取的是arm架构的镜像。然而服务器是Linux,是amd64架构的。架构不一样,容器启动失败。
使用docker inspect 镜像ID 命令能查看镜像的架构。显示是"Architecture":"arm64"。
解决方案
有2个解决方案,都很简单。
方案一:设置环境变量DOCKER\\_DEFAULT\\_PLATFORM
export DOCKER_DEFAULT_PLATFORM=linux/amd64
方案二:docker pull时指定platform
docker pull --platform linux/amd64 openjdk
扩展内容
我们知道docker镜像名由如下4部分组成:
<服务器地址>/<用户>/<仓库>:<版本>
比如镜像quay.io/coreos/etcd:v3.5.5:
- quay.io:服务器地址。表示镜像托管在quay.io。
- coreos:用户,类似于GitHub中的用户。一个用户可以维护多个仓库。
- etcd:仓库。
- v3.5.5:版本。
小Tips:
Docker镜像名<服务器地址>/<用户>/<仓库>:<版本>中,有些部分是可以省略的。
服务器地址:可省略,默认是docker.io,即DockerHub。
仓库:不能省略。
版本:可省略,取latest,即最新版本。
但其实,这4部分还不够,还不能唯一标识一个镜像。还需要镜像对应的CPU架构。
比如我的电脑是老版本Mac,是Intel的x86架构,我同事是M1的arm架构。我们执行docker pull quay.io/coreos/etcd:v3.5.5 ,下载的镜像也是不一样的。