昨天研究了 Image Manifest 的概念,提到了通常官方的 Docker Image 都有 Manifest、並提供多種架構的 image,
那既然官方的 image 可以,我們應該也可以為我們自己的 Image 建立 Manifest 吧!
因此今天延續昨天的內容,讓我們來繼續說說如何建置出支援多種架構的 image。
buildx
指令buildx 是 Docker 官方提供的一個指令,可以讓我們用來建置多種 Image,
同時在開始前,需要注意一點,
根據我的實驗,以下的指令跟步驟只能在裝有 Docker Desktop 的電腦上使用,
原因值得研究,
但直觀地猜測,是因為 Docker Desktop 的底層由 VM 架構,讓我們的開發電腦擁有建立模擬其他 CPU 架構 Image 的能力,
以下範例如果是在 Local 執行的指令就不會加上 sudo
。
buildx ls
在我的 Mac M1 電腦上執行後 buildx ls 後這些資訊,
以我目前的理解,這些是這台電腦上支援的架構,
# M1 Mac
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
default * docker
default default running 20.10.17 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
desktop-linux docker
desktop-linux desktop-linux running 20.10.17 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
而在一台 AMD64 架構的電腦上,可以看到內容有一些差別:
# AMD64 架構的伺服器
$ sudo docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
mybuilder * docker-container
mybuilder0 unix:///var/run/docker.sock running v0.10.4 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386
default docker
default default running 20.10.18 linux/amd64, linux/386
buildx create
buildx create
指令是用來執行一個「builder」,用來模擬各種架構的特殊環境,
$ docker buildx create --name mybuilder --use --bootstrap
[+] Building 3.5s (1/1) FINISHED
=> [internal] booting buildkit 3.5s
=> => pulling image moby/buildkit:buildx-stable-1 3.0s
=> => creating container buildx_buildkit_mybuilder0 0.5s
mybuilder
其中 --use
參數是用來指定為預設的 builder,--bootstrap
則是預先建立好需要的架構資料,
有興趣的讀者可以自己把這兩個參數拿掉,觀察看看有哪裡不同,
此時 Docker 會執行起一個特殊的 image,可以透過 docker ps 跟 docker images 來查看:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5bd689a0fbe4 moby/buildkit:buildx-stable-1 "buildkitd" 23 seconds ago Up 22 seconds buildx_buildkit_mybuilder0
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
moby/buildkit buildx-stable-1 21bbfc679017 6 weeks ago 134MB
buildx build
接著就到了我們最重要的建置 image,同時會上傳到 Container Registry,
我們一樣拿 D5 的程式碼範例來用,並推到 Gitlab:
$ docker buildx build --push \
--platform linux/amd64,linux/arm64 \
--tag registry.gitlab.com/louis222220/2022-ithelp-docker-is-not-so-hard/hello-world-server:multi-arch .
[+] Building 29.0s (17/17) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 136B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [linux/amd64 internal] load metadata for docker.io/library/node:16-slim 4.0s
=> [linux/arm64 internal] load metadata for docker.io/library/node:16-slim 4.0s
=> [linux/amd64 2/5] WORKDIR /app 0.3s
=> [linux/amd64 3/5] COPY ./package*.json ./ 0.0s
=> [linux/amd64 4/5] RUN npm ci 7.7s
=> [linux/arm64 2/5] WORKDIR /app 0.0s
=> [linux/arm64 3/5] COPY ./package*.json ./ 0.0s
=> [linux/arm64 4/5] RUN npm ci 0.9s
=> [linux/arm64 5/5] COPY . . 0.0s
=> [linux/amd64 5/5] COPY . . 0.0s
=> exporting to image 11.1s
=> => exporting layers 0.2s
=> => pushing layers 9.1s
=> => pushing manifest for registry.gitlab.com/louis222220/2022-ithelp-docker-is-not-so-hard/hel 1.8s
=> [auth] louis222220/2022-ithelp-docker-is-not-so-hard/hello-world-server:pull,push token for r 0.0s
可以注意到我們用了 --platform
來指定要建置的 image 架構,
接著我們再用 Server 來查看 manifest:
# AMD64 架構的 server
$ sudo docker manifest inspect registry.gitlab.com/louis222220/2022-ithelp-docker-is-not-so-hard/hello-world-server:multi-arch
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 2200,
"digest": "sha256:9becc34a5625c31a538ba232dc9d3c9d6efab9cafacacdd1536083a5a769ddb6",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 2200,
"digest": "sha256:e45d73007b3998bba9e286bf0e896b05c57c90a7f24b8830cf7ea28d86456d8a",
"platform": {
"architecture": "arm64",
"os": "linux"
}
}
]
}
可以看到成功建置多架構的 image,
最後當然還是要檢查一下,是否真的可以執行:
$ sudo docker run \
-d -p 3000:3000 \
registry.gitlab.com/louis222220/2022-ithelp-docker-is-not-so-hard/hello-world-server:multi-arch
multi-arch: Pulling from louis222220/2022-ithelp-docker-is-not-so-hard/hello-world-server
...
Digest: sha256:bbf7ea87a2d0e488f97b0549c9d2215ad03f5f6fe8a572d25af577a98457ea2c
Status: Downloaded newer image for registry.gitlab.com/louis222220/2022-ithelp-docker-is-not-so-hard/hello-world-server:multi-arch
d2983e7a83d17fae5cf36d564d05a603e1871f5caf75d42d5bbaeb9f7f474468
$ curl localhost:3000
{"hello":"world"}
Tada~ ?
完成,
那我們今天的教學就到這邊。