1.前⾔

越来越多的ARM服务器进⼊了我们的视野,docker等容器也都在跨平台编译给出了⽀持,随着国产化的需求不断加强,软件产物在国产化芯⽚交付量越来越多 ,交叉编译显得尤为重要

2.docker buildx 工具

macOS 或 Windows 系统的 Docker Desktop,以及 Linux 发⾏版通过 deb 或者 rpm 包所安装的 docker 内置了 buildx,可以使⽤命令 docker buildx 命令查看是否安装了buildx,如果没有安装的 话,可以到buildx的release下⾯⼆进制即可,安装⽅式如下:

  1. export DOCKER_BUILDKIT=1
  2. # 当然,此处使⽤的⼆进制版本可能不适合你,可以直接到https://github.com/docker/buildx/releases寻
  3. 找适合你的
  4. wget https://github.com/docker/buildx/releases/download/v0.8.2/buildx-v0.8.2.linuxamd64
  5. mv buildx-v0.8.2.linux-amd64 buildx
  6. mkdir -p ~/.docker/cli-plugins
  7. mv buildx ~/.docker/cli-plugins/docker-buildx

buildx 构建的⽅法如下:

  1. # buildx 和 docker build 命令的使⽤体验基本⼀致
  2. docker buildx build .

3.golang跨平台构建镜像示例


本人的开发环境是mac m1 芯片 服务器环境为linux arm 架构,本案例为go加载so动态库的简单demo

  1. add.c ```c

    include

    include

    include

char Add(char src, int n) { char str[20]; sprintf(str, “%d”, n); char *result = malloc(strlen(src)+strlen(str)+1); strcpy(result, src); strcat(result, str); return result; }

  1. 2. add.h
  2. ```c
  3. #ifndef __ADD_H__
  4. #define __ADD_H__
  5. char* Add(char* src, int n);
  6. #endif
  1. main.go
package main

/*
// 头文件的位置,相对于源文件是当前目录,所以是 .,头文件在多个目录时写多个  #cgo CFLAGS: ...
#cgo CFLAGS: -I./include
// 从哪里加载动态库,位置与文件名,-ladd 加载 libadd.so 文件
#cgo LDFLAGS: -L./lib -ladd -Wl,-rpath,lib
#include "add.h"
*/
import "C"
import "fmt"

func main() {
   val := C.Add(C.CString("go"), 2022)
   fmt.Println("run c: ", C.GoString(val))
}
  1. dockerfile ```dockerfile FROM golang:1.17.11-stretch

ENV CGO_ENABLED=1 ENV GOPROXY=https://goproxy.cn,direct ENV GOOS=linux ENV GOARCH=arm ENV CC=arm-linux-gnueabi-gcc ENV LD_LIBRARY_PATH=/usr/arm-linux-gnueabi/lib/ RUN apt-get update RUN apt-get install gcc-arm-linux-gnueabi -y WORKDIR /app COPY . . RUN arm-linux-gnueabi-gcc -fPIC -shared -o lib/libadd.so ./include/add.c && ln -s /usr/arm-linux-gnueabi/lib/ld-linux.so.3 /lib/ld-linux.so.3 RUN go build -o main main.go RUN export LD_LIBRARY_PATH=/usr/arm-linux-gnueabi/lib/ RUN echo $LD_LIBRARY_PATH CMD [“./main”]


5. 构建arm平台运行的镜像产物
```dockerfile
#--platform 为指定构建哪些平台的镜像产物
docker buildx build --platform linux/amd64,linux/arm64 -t demo:tag -f dockerfile --push .

4.注意

Docker 在 Linux 系统架构下是不支持 arm 架构镜像,因此我们可以运行一个新的容器让其支持该特性,Docker 桌面版则无需进行此项设置(mac系统)。
需要在内核中使用 QEMU 仿真支持来进行多架构镜像构建

# 安装模拟器(用于多平台镜像构建)
docker run --rm --privileged tonistiigi/binfmt:latest --install all
# 验证是 binfmt_misc 否开启
ls -al /proc/sys/fs/binfmt_misc/
# 验证是否启用了相应的处理器
cat /proc/sys/fs/binfmt_misc/qemu-aarch64