• Docker多平台、跨平台编译打包


    大多数带有Docker官方标识的镜像都提供了多架构支持。如:busybox镜像支持amd64arm32v5arm32v6arm32v7arm64v8i386ppc64le, and s390x。当你在amd64设备上运行容器时,会拉取amd64镜像。

    当你需要构建多平台镜像时,可以用 --platform 参数指定目标平台,但是通常情况下,你只能一次构建一个单一架构平台的镜像。如果想要一次构建多平台镜像,你需要使用docker container build driver,可以使用buildx插件进行配置,替换打包命令。

    QEMU

    跨平台打包可以使用QEMU,但是它比本机构建慢得多,依赖QEMU将本机指令转义为目标架构指令,从而实现跨平台编译。一般Linux kernel 4.8以后版本,支持binfmt-support 2.1.7及以上版本的平台,都能支持跨平台编译。你可以用以下步骤快速开启:

    docker run --privileged --rm tonistiigi/binfmt --install all
    

    为不同架构平台创建本地节点,--apend可以追加到同一个构建器中:

    1. docker buildx create --use --name mybuild node-amd64
    2. mybuild
    3. docker buildx create --append --name mybuild node-arm64

    同时构建多平台镜像:

    docker buildx build --platform linux/amd64,linux/arm64 .

    这里用buildx插件代替默认build,一次打包多平台镜像,不做过多介绍。

    交叉编译

    docker可以轻松打包多平台的镜像,但是目标程序的交叉编译取决于开发编译环境。Golang就很容易实现交叉编译,结合docker多阶段构建技术,可以实现一次编译打包多平台镜像。

    首先安装buildx插件,

    下载 

     重命名并放到docker插件目录里:

    1. mv buildx-v0.11.2.linux-amd64 docker-buildx
    2. mkdir .docker/cli-plugins -p
    3. mv docker-buildx .docker/cli-plugins/
    4. chmod +x .docker/cli-plugins/docker-buildx

    docker-compose也可以作为插件放到插件目录里,

    mv docker-compose .docker/cli-plugins/

    使用时可用如下的命令,无需使用docker-compose,这是题外话。

    docker compose up -d

     其次创建构建器,

    1. $ docker buildx ls
    2. NAME/NODE DRIVER/ENDPOINT STATUS BUILDKIT PLATFORMS
    3. mybuilder * docker-container
    4. mybuilder0 unix:///var/run/docker.sock running v0.12.3 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/arm64, linux/riscv64, linux/ppc64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
    5. default docker
    6. default default running v0.8.2+eeb7b65 linux/amd64, linux/386, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/arm/v7, linux/arm/v6

    ls命令列出已有的构建器,default是docker默认的构建器,mybuilder是我创建的构建器,可以用如下命令进行创建,

    docker buildx create --name mybuilder --bootstrap --use
    

    这条命令会创建mybuilder构建器,并启动,设置为默认构建器。

    到这里环境就算配置好了,但是要想编译打包多平台镜像,还需要编辑Dockerfile,

    1. FROM --platform=$BUILDPLATFORM golang:latest AS builder
    2. ARG TARGETARCH
    3. RUN apt-get update && apt-get install -y gcc-aarch64-linux-gnu
    4. WORKDIR /app
    5. COPY . .
    6. RUN go env -w GOOS=linux GOARCH=$TARGETARCH CGO_ENABLED=1 GOPROXY=https://goproxy.cn,direct
    7. RUN if [ "$TARGETARCH" = "arm64" ]; then go env -w AR=aarch64-linux-gnu-ar CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++; fi
    8. RUN go mod tidy
    9. RUN go build -a -ldflags '-extldflags "-static"' -o server main.go
    10. FROM alpine:latest
    11. RUN set -eux && sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories
    12. RUN apk update && apk add sqlite
    13. WORKDIR /server
    14. RUN mkdir -p /server/data
    15. COPY --from=builder /app/server /app/config.docker.yaml ./
    16. COPY --from=builder /app/resource/cert ./resource/cert
    17. EXPOSE 8660
    18. ENTRYPOINT ./server -c config.docker.yaml

    上面的Dockerfile采用多阶段构建方式支持交叉编译,多平台打包。

    第一阶段进行交叉编译

    第二阶段进行目标平台镜像打包

    里面用到docker-container驱动的环境变量有:

    BUILDPLATFORM  编译平台,即当前宿主机的平台架构

    TARGETPLATFORM

    BUILDARCH
    TARGETARCH 目标平台架构,即多平台编译打包时的目标架构

    GOARCH=$TARGETARCH 指定了Go编译目标架构 

    golang:latest、alpine:latest镜像都是支持多架构的镜像,golang:latest是基于debian构建,为了交叉编译,需要安装交叉编译环境,

    apt-get install -y gcc-aarch64-linux-gnu

     因为Go程序中用到了cgo特性,需要打开它

    CGO_ENABLED=1

    同时,如果目标平台是arm64的话,需配置go gcc等编译器环境变量

    RUN if [ "$TARGETARCH" = "arm64" ]; then go env -w AR=aarch64-linux-gnu-ar CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++; fi

    当然,第一步也可以直接在目标平台编译,不过速度有点洗人:

    1. FROM --platform=$TARGETPLATFORM golang:1.21 AS builder
    2. ARG TARGETARCH
    3. RUN set -eux && sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list.d/debian.sources
    4. RUN apt-get update && apt-get install -y libssl-dev g++
    5. WORKDIR /app
    6. COPY . .
    7. RUN go env -w GOOS=linux GOARCH=$TARGETARCH CGO_ENABLED=1 GOPROXY=https://goproxy.cn,direct
    8. RUN go mod tidy
    9. RUN go build -a -ldflags '-extldflags "-static"' -o server main.go

    最后,执行buildx命令

    docker buildx build --platform linux/arm64,linux/amd64 -t 172.16.60.12:8888/star/iot-go . --push

    编译打包多平台镜像并推送到仓库中。也可以输出单一平台,并保存到本地,

    docker buildx build --platform linux/arm64 -t star/iot-go . --load

    参考资料:

    Multi-platform images | Docker Docs

    How to use docker buildx to build multi-architecture Go images

  • 相关阅读:
    SSH配置免密登录
    DALL·E 3 & ChatGPT-4的梦幻联动
    java python构造器&变量的区别
    pytorch 入门 (三)案例一:mnist手写数字识别
    干扰管理学习日志6--------干扰管理综述(2021)
    大规模分布式链路分析计算在字节跳动的实践
    预处理指令
    开源轻量堡垒机——Teleport的安装配置和使用
    JavaScript中常用对象方法总结
    python基础语法(十)
  • 原文地址:https://blog.csdn.net/ilyz5609/article/details/134059328