我在前陣子開發專案的過程中,才發現了原來不同 CPU 架構的電腦,會需要使用不同的 Docker Image,
仔細想想也是合理,Docker 是跑在 OS 之上的,不同的 OS 跟 CPU 架構,當然就要有不同的 Image,
因此今天來研究,關於不同 CPU 架構的 Docker Image。
電腦的 CPU 有多種不同的架構,舉例 Mac 在 M1 以前的是使用 Intel 生產的 CPU,是 x86 架構,而從 M1 開始則是 ARM 架構的 CPU,
然後,關於 CPU 架構的議題再講下去,恐怕有點太硬核了, 硬核到我也不太懂, 讀者只要知道,不同架構的電腦會需要使用對應架構的 Image 就好,
有興趣的讀者可以稍微參考一下 WikiPedia - 指令集架構。
在一台電腦、或 Server 上,想要知道目前的 Docker image 是什麼架構,可以用 inspect 指令來取得,以我在 D5 - Hello World ft. Express 的 Image 為例:
$ sudo docker inspect registry.gitlab.com/louis222220/2022-ithelp-docker-is-not-so-hard/hello-world-server
[
{
"Id": "sha256:7ed15d3c7871650f7747f91b60b37457b47c172b86d2b8fa529b0981be5118b0",
...
"Architecture": "amd64",
"Os": "linux",
...
}
]
根據 Architecture
、Os
這兩個屬性,
可以看到當時我們建出來的 Docker Image 是 AMD64 的架構,
而我用目前 Mac M1 電腦建置出來的 Image,則是 ARM64v8 的架構:
[
{
"Id": "sha256:a6f98b4b2c708863fa52402424b40a75f58579f920e67a8516c9bcf0bc40d0ac",
...
"Architecture": "arm64",
"Variant": "v8",
"Os": "linux",
...
}
]
雖然 ARM 跟 AMD 在視覺上看起來很像,但它們是兩種不同的架構。
那如果在 M1 電腦上執行 AMD64 架構的 Image 會怎麼樣呢?
剛剛實際嘗試了一次,直接把儲存在 Gitlab Container Registry 上的 Image 拉下來到 M1 電腦上跑起來:
$ docker run -p 80:80 -d registry.gitlab.com/louis222220/2022-ithelp-docker-is-not-so-hard/hello-world-server
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
4bbaa421c104574b89a6e07f6f0b32e142e03fb9be5bb8fb57d195f0bd20acf0
Docker 先貼心地提醒了我們,表示這個 Image 架構跟目前的 OS 環境是不吻合的,但 Container 依然有被建立出來,
然而實際連進 Container,會發現根本什麼都不會動,看來不同架構就是不能跑 (笑)。
既然不同架構的 Image 不能混用,那就表示我們執行 docker pull 指令時,docker 會自動辨識並抓取對應架構的 Image 來使用,
Docker 採取的方法就被稱為 Manifest
,猜測是取這個單字「清單」的涵義,docker 透過 manifest 這個清單,來決定要使用哪一個 image,多數的官方 Image 都有提供不同的架構,因此一般使用者大概不會馬上發現這個差異,
用來查看 Manifest 的指令:
$ docker manifest inspect node:16-slim
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1367,
"digest": "sha256:cf6f2b5db9748ffdf84c382c0bdfd14c47e458cc244090feae099efda6523a72",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1367,
"digest": "sha256:a772961d77beff07ae84f76c0de2526a2e20881d0135a869f19a34e85175b776",
"platform": {
"architecture": "arm",
"os": "linux",
"variant": "v7"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 1367,
"digest": "sha256:9500597a304829398b5a7fc67d947ac14281810a2ce0038146d04b81443141e6",
"platform": {
"architecture": "arm64",
"os": "linux",
"variant": "v8"
}
}
]
}
可以看到其中有三種架構,分別是 AMD64、ARMv7、及 ARM64v8,
那今天的研究就先到這邊,下次我們再繼續瞭解要如何在自己的 Container Registry 建立 Manifest。