1.前⾔
越来越多的ARM服务器进⼊了我们的视野,docker等容器也都在跨平台编译给出了⽀持,随着国产化的需求不断加强,软件产物在国产化芯⽚交付量越来越多 ,交叉编译显得尤为重要
2.docker buildx 工具
macOS 或 Windows 系统的 Docker Desktop,以及 Linux 发⾏版通过 deb 或者 rpm 包所安装的 docker 内置了 buildx,可以使⽤命令 docker buildx 命令查看是否安装了buildx,如果没有安装的 话,可以到buildx的release下⾯⼆进制即可,安装⽅式如下:
export DOCKER_BUILDKIT=1# 当然,此处使⽤的⼆进制版本可能不适合你,可以直接到https://github.com/docker/buildx/releases寻找适合你的wget https://github.com/docker/buildx/releases/download/v0.8.2/buildx-v0.8.2.linuxamd64mv buildx-v0.8.2.linux-amd64 buildxmkdir -p ~/.docker/cli-pluginsmv buildx ~/.docker/cli-plugins/docker-buildx
buildx 构建的⽅法如下:
# buildx 和 docker build 命令的使⽤体验基本⼀致docker buildx build .
3.golang跨平台构建镜像示例
本人的开发环境是mac m1 芯片 服务器环境为linux arm 架构,本案例为go加载so动态库的简单demo
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; }
2. add.h```c#ifndef __ADD_H__#define __ADD_H__char* Add(char* src, int n);#endif
- 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))
}
- 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
