效果预览 本机:X86_64 Windows(Docker Desktop)+WSL(Ubuntu)。
arm(鲲鹏,飞腾,苹果M系列)
mips64(龙芯3A4000及之前)
x86(intel、amd、海光、兆芯)
这里没有使用交叉编译工具进行编译,因为我们最终项目打包的是docker镜像。使用多阶段构建镜像时,此阶段只作为中间产物。
核心:通过编写Dockerfile,使程序在对应架构docker容器中进行编译,编译后导出二进制可执行文件
访问国外网站🪜后访问官方仓库:https://hub.docker.com/
以查询golang(包含go环境)镜像为例,搜索golang,第一个后面带的图标即为官方镜像
点击golang进入,点击Tags即可看到所有的版本和支持的架构
重命名主要为方便后续,如果电脑能访问外网也可不重命名,每次使用时自动去拉取镜像。
arm64
docker pull --platform=linux/arm64 golang:1.23.0
重命名:
docker tag golang:1.23.0 goalng-arm64:1.23.0
mips64
对应mips64le
docker pull --platform=linux/mips64le golang:1.23.0
重命名:
docker tag golang:1.23.0 goalng-mips64le:1.23.0
x86
对应amd64
由于本机为intel处理器,镜像默认使用amd架构docker pull golang:1.23.0
重命名:
docker tag golang:1.23.0 goalng-amd64:1.23.0
最后效果如下:
要将构建结果导出为文件,您可以使用local
导出器。local
导出器会将构建容器的文件系统保存到主机上的指定目录中。
要使用local
导出器,请将--output
选项传递给docker build
命令。该--output
标志带有一个参数:主机上要保存文件的目标位置。
以下命令将server
目标中的文件导出到主机文件系统上的当前工作目录:
$ docker build --output=. --target=server .
Dockerfile中可添加一个阶段如下:
FROM scratch AS server
COPY --from=build-server /bin/server /bin/
执行构建
docker build --output=./test --target=binaries .
arm
FROM --platform=linux/arm64 goalng-arm:1.23.0 as builder
#将上层整个文件夹拷贝到/build
ADD . /build/src
WORKDIR /build/src
#去掉了调试信息 -ldflags="-s -w" 以减小镜像尺寸
RUN go env -w GOPROXY=https://goproxy.cn,direct && go build -ldflags="-s -w" -o ipm ./cmd/publish/main.go
FROM scratch AS binaries
COPY --from=builder /build/src/ipm /
执行构建
docker build --output=./test --target=binaries .
此时宿主机当前目录的test下出现ipm二进制文件,实现arm版本打包
修改Dockerfile
FROM --platform=linux/mips64le goalng-mips:1.23.0 as builder
#将上层整个文件夹拷贝到/build
ADD . /build/src
WORKDIR /build/src
#去掉了调试信息 -ldflags="-s -w" 以减小镜像尺寸
RUN go build -ldflags="-s -w" -o ipm ./cmd/publish/main.go
FROM scratch AS binaries
COPY --from=builder /build/src/ipm /
执行构建
docker build --output=./test --target=binaries .
验证
root@DESKTOP-BB0KRFQ:/mnt/d/projects/csmp/ipm# file ./test/ipm
./test/ipm: ELF 64-bit LSB executable, MIPS, MIPS64 rel2 version 1 (SYSV), dynamically linked, interpreter /lib64/ld.so.1, BuildID[sha1]=9d8b3a06637b96230a5eb81e2e363d81705ea084, for GNU/Linux 3.2.0, stripped
x86_64
由于本机为该架构,常规方式即可,这里不再演示。通过定义变量,接收`docker build`时传入参数来打包不同架构镜像
# syntax=docker/dockerfile:1
ARG PLATFORM=$TARGETPLATFORM
ARG ARCH=$TARGETARCH
ARG ALPINE_VERSION=3.20
ARG GO_VERSION=1.23.0
# 多阶段构建
#构建一个 builder 镜像,目的是在其中编译出可执行文件mck
#构建时需要将此文件放到代码根目录下
FROM --platform=${PLATFORM} golang-${ARCH}-zf:${GO_VERSION}-alpine${ALPINE_VERSION} as builder
#将上层整个文件夹拷贝到/build
ADD . /build/src
WORKDIR /build/src
#去掉了调试信息 -ldflags="-s -w" 以减小镜像尺寸
RUN go env -w GO111MODULE=on \
&& go env -w GOPROXY=https://goproxy.cn,direct \
&& go env -w CGO_ENABLED=0 \
&& go mod tidy \
&& go build -ldflags="-s -w" -o ha /build/src/cmd/ha/main.go
FROM --platform=${PLATFORM} alpine-${ARCH}:${ALPINE_VERSION}
WORKDIR /home
COPY --from=builder /build/src/configs/config.yml /home/configs/config.yml
COPY --from=builder /build/src/ha /home/ha
CMD ["home/ha"]
#EXPOSE 9681
#docker run -d --name ha -p 9680:9680 -v /etc/localtime:/etc/localtime ha
# docker run -d --pid=host --privileged=true -p 9680:9680 -v /etc/sysconfig/network-scripts:/etc/sysconfig/network-scripts -v /etc/localtime:/etc/localtime ha
arm
构建时docker build -t ipm-arm:v4.0.0 --platform=linux/arm64 .
mips
docker build -t ipm-mips:v4.0.0 --platform=linux/mips64le .
x86_64
docker build -t ipm-amd:v4.0.0 --platform=linux/amd64 .
vim /etc/docker/daemon.json
添加以下内容
{
"experimental": true, //低版本docker时需要添加此行
"features": {
"containerd-snapshotters": true
}
}
重启docker服务
systemctl daemon-reload
systemctl restart docker.service
安装模拟器
apt-get install qemu qemu-user-static binfmt-support
老版本docker中,如果Dockerfile from的镜像已经在amd机器上存在,则不会去下载arm64镜像,打包出的镜像是amd64的。需要先下载对应平台的基础镜像,再使用docker build --platform=linux/arm64