構建支持多平臺的docker鏡像
構建支持多平臺的docker鏡像
一、思路
近期團隊在進行服務/軟件的多平臺(多CPU架構,例如:arm、mips等)改造,由于服務已經docker化,所以只需制作對應平臺的鏡像即可。
最先想到的就是在tag名這里做文章,例如:
docker.open-open.com/test:1.0-x86_64
docker.open-open.com/test:1.0-arm64
docker.open-open.com/test:1.0-mips64
或者
docker.open-open.com/x86_64/test:1.0
docker.open-open.com/arm64/test:1.0
docker.open-open.com/mips64/test:1.0
在每臺目標機上構建鏡像,并通過架構名來區分。這種方式,在運維層面需要額外的工作,例如運行腳本、編排文件等都需要維護多套。
我們在查看docker hub的tags時,可以看到 docker 鏡像倉庫是支持多個平臺的
使用時,也只需簡單的 docker pull 鏡像名、docker run 鏡像名,docker cli會根據本機CPU架構選擇合適的鏡像文件。
要制作支持多平臺的docker鏡像,有2種方式
docker manifest
需要 docker 版本不低于 18buildlx
需要 docker 版本不低于 19.03
二、開啟實驗性功能
docker manifest和buildlx 都需要開啟實驗性功能,默認是關閉的。
2.1 添加docker client的使用參數
$ mkdir ~/.docker/ -p
$ vim ~/.docker/config.json
添加如下內容
{
"experimental": "enabled"
}
如果 ~/.docker/config.json 文件已經存在,只需添加"experimental": "enabled"
2.2 驗證是否開啟
執行 docker version
$ docker version | grep -Pzo 'Client(.|\n)*\n\n'
Client: Docker Engine - Community
Version: 19.03.5
API version: 1.40
Go version: go1.12.12
Git commit: 633a0ea
Built: Wed Nov 13 07:25:41 2019
OS/Arch: linux/amd64
Experimental: true
Experimental: true 表示已開啟
執行 docker --help
$ docker --help | grep -iE 'manifest|buildx'
buildx* Build with BuildKit (Docker Inc., v0.3.1-tp-docker)
manifest Manage Docker image manifests and manifest lists
出現 buildx 和 manifest 2行說明,就表示可以使用buildx、manifest
三、使用 docker manifest
3.1 創建 manifest 列表
- 使用格式
$ docker manifest create --help
Usage: docker manifest create MANIFEST_LIST MANIFEST [MANIFEST...]
- 示例
$ docker manifest create docker.open-open.com/service_dev:1.0.0 \ docker.open-open.com/service_dev:1.0.0-x86_64 \ docker.open-open.com/service_dev:1.0.0-arm64 \ docker.open-open.com/service_dev:1.0.0-mips64
注意:
manifest 對應的鏡像,需要在目標機上構建,并上傳到鏡像倉庫中
3.2 上傳 manifest 列表
- 使用格式
$ docker manifest push --help
Usage: docker manifest push [OPTIONS] MANIFEST_LIST
- 示例
$ docker manifest push docker.open-open.com/service_dev:1.0.0
sha256:c62005140cd5368a8a18bdb0e0dcbcb9e24a04ceb1e22518dd9501cd979c9c50
3.3 查看 manifest 清單
- 使用格式
$ docker manifest inspect --help
Usage: docker manifest inspect [OPTIONS] [MANIFEST_LIST] MANIFEST
- 示例
$ docker manifest inspect docker.open-open.com/service_dev:1.0.0
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 4724,
"digest": "sha256:f36faf79ac9f430f6e212d21bed24a4edc20e46b22ae422e83a14329b2300fbc",
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 4724,
"digest": "sha256:74b99f5527450769579f93613c06cf67acf33f932d2a566d206e855b55ed484e",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 4724,
"digest": "sha256:3578489111d40b42d422b415c3584c831e56ca9e8fbf6c416ff49814e2bd088c",
"platform": {
"architecture": "mips64le",
"os": "linux"
}
}
]
}
四、使用 buildlx
4.1 安裝buildx
- 下載buildx
官方地址:https://github.com/docker/buildx/releases
$ wget https://github.com/docker/buildx/releases/download/v0.4.1/buildx-v0.4.1.linux-amd64
安裝
$ mkdir ~/.docker/cli-plugins/ $ cp buildx-v0.4.1.linux-amd64 ~/.docker/cli-plugins/docker-buildx $ chmod +x ~/.docker/cli-plugins/docker-buildx
查看
$ docker buildx version github.com/docker/buildx v0.4.1 bda4882a65349ca359216b135896bddc1d92461c
4.2 添加多架構支持
默認支持的架構
$ docker buildx ls NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS default * docker default default running linux/amd64, linux/386
注:
每個架構下面執行的結果不一樣新增
$ docker run --privileged --rm tonistiigi/binfmt --install all $ docker buildx create --use --name mybuilder $ docker buildx inspect --bootstrap
查看
$ docker buildx ls
NAME/NODE DRIVER/ENDPOINT STATUS PLATFORMS
mybuilder * docker-container
mybuilder0 unix:///var/run/docker.sock running linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
default docker
default default running linux/amd64, linux/386
注意
如果重啟了機器,需要重新執行
$ docker run --privileged --rm tonistiigi/binfmt --install all
tonistiigi/binfmt 不支持misp,要自行修改代碼
cmd/binfmt/config.go 中添加mips的支持
"mips64el": {
binary: "qemu-mips64el",
magic: `\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00`,
mask: `\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff`,
},
4.3 構建鏡像
Dockerfile文件不需要改的
構建命令用 docker buildx build 代替 docker build
示例
$ docker buildx build --platform linux/arm64,linux/amd64,linux/mips64le . \
-t docker.open-open.com/service_dev:1.0.0 --push
參數--push
表示構建成功后,上傳鏡像
成功后可以用docker manifest inspect 鏡像名
或者 docker buildx imagetools inspect 鏡像名
查看
示例
$ docker buildx imagetools inspect docker.open-open.com/service_test:1.0.34r
Name: docker.open-open.com/service_test:1.0.34r
MediaType: application/vnd.docker.distribution.manifest.list.v2+json
Digest: sha256:a615d286c00fee23654a135f53c3d5dbd3f2d3621d3cd99d22ba98c6f81b05f9
Manifests:
Name: docker.open-open.com/service_test:1.0.34r@sha256:de698defff054380a4ea792c678007cfb2ccf209457c729402979e4a6b753f67
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/arm64
Name: docker.open-open.com/service_test:1.0.34r@sha256:bb56ac0b075634b29d20bdbc6b630a6ca9579920605f0dfdd62d67422dd16c19
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/amd64
Name: docker.open-open.com/service_test:1.0.34r@sha256:54a989e94e9b1a23475a202ead2aeab00c9d8b5963f371edc71ffbe87176cee7
MediaType: application/vnd.docker.distribution.manifest.v2+json
Platform: linux/mips64le
五、manifest 與 buildlx 選擇
buildlx 的優點:
- 可以不要目標平臺的設備,在本機就可以構建出多個平臺(例如:arm、mips等)的鏡像
- 構建方式簡潔,只需修改構建命令
buildlx 的缺點:
- 由于 buildlx 使用 QEMU,構建時,如果需要編譯(例如:c/c++),速度非常慢,往往10多分鐘就可以編譯好的,卻要花費好幾個小時
- 有時候會卡死(中斷重新構建,可以解決問題)
- 有時候會編譯失敗(無法解決)
- 有時候編譯出來的鏡像,在目標機器上無法運行(無法解決)
manifest 的優點:
- 兼容性好
- 構建速度快
manifest 的缺點:
- 需要有目標平臺的設備
- 比 buildlx 略繁瑣
- manifest 列表 create 后,無法刪除內部的manifest。鏡像變動了,tag必須也變動
我們在實際使用中優先采用的是 buildlx,只有 buildlx 無法編譯或構建的鏡像無法使用時才會采用manifest。
六、基礎鏡像(base)的選擇
要構建多平臺的鏡像,那么基礎鏡像也要支持相應的平臺。這個可以到docker hub去看,我們最終選擇的是debian:buster-slim
。
debian:buster-slim
支持的平臺很全面,國內的龍芯、飛騰、鯤鵬都可以使用。體積也非常的小。
沒有采用Alpine
,因為有些項目在非x86_64上編譯通不過。
參考文章
https://docs.docker.com/engine/reference/commandline/manifest/
https://www.docker.com/blog/multi-arch-images/
https://github.com/docker/buildx/