侧边栏壁纸
  • 累计撰写 48 篇文章
  • 累计创建 7 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

基于Docker的交叉编译和打包多平台架构镜像

Administrator
2024-09-10 / 0 评论 / 0 点赞 / 2 阅读 / 0 字

效果预览

本机:X86_64 Windows(Docker Desktop)+WSL(Ubuntu)。

本文将详细讲解如何在Windows上打包x86,arm,mips二进制文件和镜像

1.1 交叉编译的二进制文件

arm(鲲鹏,飞腾,苹果M系列)

mipse64(龙芯3A4000及之前)

x86(intel、amd、海光、兆芯)

1.2 多平台架构镜像

![](https://cdn.nlark.com/yuque/0/2024/png/12795725/1726111100542-cc5d5260-213e-44b5-907c-86111970d87d.png)

基于Docker的交叉编译

这里没有使用交叉编译工具进行编译,因为我们最终项目打包的是docker镜像,使用多阶段构建镜像时,

核心:通过编写Dockerfile,使程序在对应架构docker容器中进行编译,编译后导出二进制可执行文件

2.1 镜像获取

科学上网🪜后访问官方仓库: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

最后效果如下:

2.2 导出文件知识

要将构建结果导出为文件,您可以使用`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 .

2.3 编写Dockerfile

+ `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版本打包

  • mipse64打包

修改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 由于本机为该架构,常规方式即可,这里不再演示。

打包多平台镜像

3.1 修改Dockerfile,使不同平台共用一个。

通过定义变量,接收`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

3.2 构建

+ `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-mips:v4.0.0 --platform=linux/amd64 .

在Linux 多平台支持

```plain 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

最终优化版Dockefile

```plain # syntax=docker/dockerfile:1

ARG PLATFORM=$TARGETPLATFORM ARG ARCH=$TARGETARCH ARG ALPINE_VERSION=3.20 ARG GO_VERSION=1.23.0

多阶段构建

#构建一个 builder 镜像,目的是在其中编译出可执行文件 FROM --platform=${PLATFORM} golang-${ARCH}-zf:${GO_VERSION}-alpine${ALPINE_VERSION} as builder

WORKDIR /build/src #RUN go env -w GOPROXY=https://goproxy.cn,direct #使用缓存进行构建,加快构建速度 RUN --mount=type=cache,target=/go/pkg/mod/
--mount=type=bind,source=go.sum,target=go.sum
--mount=type=bind,source=go.mod,target=go.mod
go mod download -x

RUN --mount=type=cache,target=/go/pkg/mod/
--mount=type=bind,target=.
CGO_ENABLED=0 GOARCH=$ARCH go build -ldflags="-s -w" -o /bin/server ./cmd/ha/main.go

构建最终镜像

FROM --platform=${PLATFORM} alpine-${ARCH}:${ALPINE_VERSION} AS final

#COPY ./configs/config.yml /bin/configs/config.yml COPY --from=builder /bin/server /bin/

EXPOSE 9681 ENTRYPOINT [ "/bin/server" ]

#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

构建arm64镜像:docker build -t test:v1 --platform=linux/arm64 .

构建amd64镜像:docker build -t test:v1 --platform=linux/amd64 .


0

评论区