• 使用buildx实现Docker跨平台编译


    使用buildx实现Docker跨平台编译

    背景

    传统CDN价格比较昂贵,PCDN资源使用节约成本的一种思路,而市面上的盒子资源往往使用的都是ARM32和ARM64的架构,部署方式往往都是使用Docker部署,我们需要打多个镜像来适配不同的架构。如果想要在自己的服务器上制作镜像,往往会出现千奇百怪的问题。

    构建ARM镜像的方法主要为下面这几种

    • 在ARM设备上进行编译(最新的Mac都是ARM64架构)
    • 模拟ARM环境,可以使用QEMU实现(参考博客:https://blog.csdn.net/xiaofengxing1/article/details/105490843/)
    • 交叉编译,交叉编译器可以编译出另一个系统平台的可执行文件,可以参考Golang的编译,支持的特别友好。

    构建多平台的Docker镜像

    Docker 在19.03版本引入了新的插件buildx,可以实现构建多平台的Docker镜像。

    开启buildx功能

    使用19.X版本还需要进行一些配置才可以开启,在20.X版本Docker默认开启了buildx。下面说下19.x的开启方法

    #开启环境变量
    export DOCKER_CLI_EXPERIMENTAL=enabled
    ##验证:
    docker buildx version
    	github.com/docker/buildx v0.6.1-docker 260d07a9a19b03df969787496419a0808a27ac61
    #启用binfmt_misc(Mac跳过)
    docker run --rm --privileged docker/binfmt:66f9012c56a8316f9244ffd7622d7c21c1f6f28d
    #验证
    ls  /proc/sys/fs/binfmt_misc/
    	qemu-aarch64  qemu-arm  qemu-ppc64le  qemu-s390x  register  status
    cat /proc/sys/fs/binfmt_misc/qemu-aarch64
      enabled
      interpreter /usr/bin/qemu-aarch64
      flags: OCF
      offset 0
      magic 7f454c460201010000000000000000000200b7
      mask ffffffffffffff00fffffffffffffffffeffff
    

    创建并使用多平台构建器

    #创建
    docker buildx create --use --name mybuilder
    #启动
    docker buildx inspect mybuilder --bootstrap
    +] Building 18.9s (1/1) FINISHED
     => [internal] booting buildkit                                           18.9s
     => => pulling image moby/buildkit:buildx-stable-1                        18.2s
     => => creating container buildx_buildkit_mybuilder0                       0.6s
    Name:   mybuilder
    Driver: docker-container
    
    Nodes:
    Name:      mybuilder0
    Endpoint:  unix:///var/run/docker.sock
    Status:    running
    Platforms: linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
    

    构建多平台镜像

    使用一个goalng代码进行测试

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    )
    
    func listenServer() {
    	http.Handle("/", http.HandlerFunc(lServe))
    	http.ListenAndServe(":8080", nil)
    }
    
    func lServe(w http.ResponseWriter, r *http.Request) {
    	log.Println("response success")
    	fmt.Fprintln(w, "hello world")
    }
    func main() {
    	listenServer()
    }
    

    Dockerfile文件

    FROM golang:alpine
    MAINTAINER jiangfeng
    WORKDIR $GOPATH/src/test
    ADD . ./
    ENV GO111MODULE=on
    ENV GOPROXY="https://goproxy.io"
    RUN go build -o test_docker .
    EXPOSE 8080
    ENTRYPOINT  ["./test_docker"]
    

    使用Docker buildx进行构建

    docker buildx build -t jiangfeng2010/buildx_test --platform=linux/arm/v7,linux/arm64,linux/amd64 . --push
    

    过程如下:

    如果只是想保留到本地,可以使用如下命令

    docker buildx build -t jiangfeng2010/buildx_test --platform=linux/arm64 -o type=docker .
    

    查看镜像digests:

    docker buildx imagetools inspect jiangfeng2010/buildx_test
    Name:      docker.io/jiangfeng2010/buildx_test:latest
    MediaType: application/vnd.docker.distribution.manifest.list.v2+json
    Digest:    sha256:49ec85eb495d740b3fa9dae75fb22616c4f6484a019f97ad8e1c56eb9e888469
    
    Manifests:
      Name:      docker.io/jiangfeng2010/buildx_test:latest@sha256:ee3d8adecd00615a14d25499344981c462c1da1d87e34f48f2215a9a628c502e
      MediaType: application/vnd.docker.distribution.manifest.v2+json
      Platform:  linux/arm/v7
    
      Name:      docker.io/jiangfeng2010/buildx_test:latest@sha256:c5600c69cc83ea4204b8717a58fc4cb107ebaab9cc42c480041f7f3bc68de11e
      MediaType: application/vnd.docker.distribution.manifest.v2+json
      Platform:  linux/arm64
    
      Name:      docker.io/jiangfeng2010/buildx_test:latest@sha256:8a27ba2ad897f7857dff83df617aac8c6ce2185d9d327f1342dc7d8a659c0642
      MediaType: application/vnd.docker.distribution.manifest.v2+json
      Platform:  linux/amd64
    

    问题与思考

    1.针对不同的架构,我们往往使用的是不同的基础镜像,比如制作ARM32的设备,我们一般会使用arm32v7/debian,在arm64的设备上,我们使用的是arm64v8/debian:10,其实使用buildx的时候只是交叉编译的某一个架构的专属镜像,改如何解决这个问题,一键打包多平台的镜像。

    2.传统的盒子资源内存都是十分宝贵的,虚盒资源也希望镜像越小越好,以上面做的测试为例,镜像达到了惊人的300M,这会导致部分盒子跑步起来的情况,如何能把镜像做到50M以内。

  • 相关阅读:
    Android 画布绘图
    Android 4.2.2原生Launcher修改使之可以运行过程小结
    canvas的translate、scale、rotate等方法
    WorkSpace介绍
    Libgdx New 3D API 教程之 -- 加载3D场景的背后-第二部分
    Libgdx New 3D API 教程之 -- 使用Libgdx加载模型
    LibGdx----Texture, TextureRegion, SpriteBatch
    libgdx学习之Camera
    Java伪代码
    读大道至简之感
  • 原文地址:https://www.cnblogs.com/feng0919/p/15953084.html
Copyright © 2020-2023  润新知