本篇中,我们构建能够在 Linux 发行版中执行的容器镜像,所以编译目标系统环境变量GOOS统一设置为linux。执行代码段0-4中的命令构建出二进制文件备用。
// 代码段-04 #!/bin/bash IMAGE?=kofj/multi-demo NOCOLOR:='\033[0m' RED:='\033[0;31m' GREEN:='\033[0;32m' BUILD_ARCH?=$(uname -m) BUILD_OS?=$(uname -s) BUILD_PATH:=build/docker/linux LINUX_ARCH?=amd64 arm64 riscv64 LDFLAGS:="-s -w -X github.com/kofj/multi-arch-demo/cmd/info.BuildArch=$(BUILD_ARCH) -X github.com/kofj/multi-arch-demo/cmd/info.BuildOS=$(BUILD_OS)" for arch in ${LINUX_ARCH}; do echo ===================; echo ${GREEN}Build binary for ${RED}linux/$$arch${NOCOLOR}; echo ===================; GOARCH=$$arch GOOS=linux go build -o ${BUILD_PATH}/$$arch/webapp -ldflags=${LDFLAGS} -v cmd/main.go; done 构建各个平台的镜像首先,我们编写一个 Dockerfile用于构建镜像。
FROM scratch LABEL authors="Fanjian Kong" ADD webapp /app/ WORKDIR /app CMD ["/app/webapp"]然后,分别构建不同平台的镜像,可以使用如代码段-05的脚本帮助构建。
// 代码段-05 #!/bin/bash IMAGE?=kofj/multi-demo NOCOLOR:='\033[0m' RED:='\033[0;31m' GREEN:='\033[0;32m' LINUX_ARCH?=amd64 arm64 riscv64 BUILD_PATH:=build/docker/linux for arch in ${LINUX_ARCH}; do echo =================== ; echo ${GREEN}Build docker image for ${RED}linux/$$arch${NOCOLOR} ; echo =================== ; cp Dockerfile.slim ${BUILD_PATH}/$$arch/Dockerfile ; docker build -t ${IMAGE}:$$arch ${BUILD_PATH}/$$arch ; done 创建 Manifest List我们使用docker manifest 子命令管理 manifest list。其中,docker manifest create 子命令用于在本地创建一个 manifest list。该命令需要指定待 manifest list 地址和一系列的 manifests。例如需要创建包含amd64和 arm64 两个平台镜像的 manifest list,则命令如:
docker manifest create kofj/multi-demo kofj/multi-demo:amd64 kofj/multi-demo:arm64docker manifest create 命令的详细帮助信息如下所示:
# docker manifest create --help Usage: docker manifest create MANIFEST_LIST MANIFEST [MANIFEST...] Create a local manifest list for annotating and pushing to a registry Options: -a, --amend Amend an existing manifest list --insecure Allow communication with an insecure registry我们按照上述方法创建出来的 manifest list 中并没有说明其中的 manifest 是什么操作系统和平台的,docker manifest annotate 命令用于注释创建出来的 manifest list。例如注释某个 manifest 是 linxu系统 arm64 平台的,则命令:
docker manifest annotate kofj/multi-demo kofj/multi-demo:arm64 --os linux --arch arm64docker manifest annotate 命令的详细帮助信息如下所示:
# docker manifest annotate --help Usage: docker manifest annotate [OPTIONS] MANIFEST_LIST MANIFEST Add additional information to a local image manifest Options: --arch string Set architecture --os string Set operating system --os-features strings Set operating system feature --variant string Set architecture variant注意:
创建 manifest list 清单的过程中会检查远端仓库中 manifests 是否存在,所以我们必修提前推送镜像到远端。如果远端仓库是不安全的,在创建的过程中需要添加参数 --inseure。
使用 docker manifest annotate 注释 manifest list 的时候不需要使用--insecure。
为了方便使用,我们可以使用下述代码段-06 的脚本创建 manifest list。
// 代码段-06 #!/bin/bash IMAGE?=kofj/multi-demo NOCOLOR:='\033[0m' RED:='\033[0;31m' GREEN:='\033[0;32m' LINUX_ARCH?=amd64 arm64 riscv64 IMAGES=$(foreach arch,$(LINUX_ARCH),$(IMAGE):$(arch)) @echo ${GREEN}Create manifest for ${RED} \( ${LINUX_ARCH}\) ${NOCOLOR}; @docker manifest create ${IMAGE} ${IMAGES} @for arch in ${LINUX_ARCH}; do \ echo ${GREEN}Annotate manifest ${RED}linux/$$arch${NOCOLOR}; \ echo ===================; \ docker manifest annotate ${IMAGE} ${IMAGE}:$$arch --os linux --arch $$arch; \ done 推送 manifest list当我们完成 manifest list 的创建工作后,它还是存储在本地的。这时候,还需要推送到远端的镜像仓库。与推送普通镜像不同,推送 manifest list 需要使用 docker manifest push 命令进行。如果我们要推送 kofj/multi-demo 这个 manifest list,则命令如:
docker manifest push kofj/multi-demo使用 docker manifest push 命令可以通过附加--purge 选项在推送完成后删除存储在本地的 manifest list; 当我们的目标仓库没有使用或者使用了非可信 TLS 证书的时候,则需要使用 --insecure 选项。
buildx 自动构建 软件依赖Docker >= 19.03: 自该 Docker 版本包含 buildx。
Linux kernel >= 4.8: 自该Linux内核版本 binfmt_misc 支持 fix-binary (F) flag。fix_binary 标志允许内核在容器或chroot内使用binfmt_misc注册的二进制格式处理程序,即使该处理程序二进制文件不是该容器或chroot内可见的文件系统的一部分。
binfmt_misc file system mounted: 需要挂载binfmt_misc文件系统,以便用户空间工具可以控制此内核功能,即注册和启用处理程序。