前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >基于Docker的交叉编译和打包多平台镜像

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

作者头像
编码如写诗
发布2024-09-12 19:08:39
1140
发布2024-09-12 19:08:39
举报
文章被收录于专栏:编码如写诗

效果预览 本机:X86_64 Windows(Docker Desktop)+WSL(Ubuntu)。

1.1 交叉编译的二进制文件

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

mips64(龙芯3A4000及之前)

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

1.2 多平台架构镜像

基于Docker的交叉编译

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

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

2.1 镜像获取

访问国外网站🪜后访问官方仓库:https://hub.docker.com/

以查询golang(包含go环境)镜像为例,搜索golang,第一个后面带的图标即为官方镜像

点击golang进入,点击Tags即可看到所有的版本和支持的架构

下载和重命名镜像

重命名主要为方便后续,如果电脑能访问外网也可不重命名,每次使用时自动去拉取镜像。

  • arm64
代码语言:javascript
复制
docker pull --platform=linux/arm64 golang:1.23.0

重命名:

代码语言:javascript
复制
docker tag golang:1.23.0 goalng-arm64:1.23.0
  • mips64 对应mips64le
代码语言:javascript
复制
docker pull --platform=linux/mips64le golang:1.23.0

重命名:

代码语言:javascript
复制
docker tag golang:1.23.0 goalng-mips64le:1.23.0
  • x86 对应amd64由于本机为intel处理器,镜像默认使用amd架构
代码语言:javascript
复制
docker pull  golang:1.23.0

重命名:

代码语言:javascript
复制
docker tag golang:1.23.0 goalng-amd64:1.23.0

最后效果如下:

2.2 导出文件知识

要将构建结果导出为文件,您可以使用local导出器。local导出器会将构建容器的文件系统保存到主机上的指定目录中。

要使用local导出器,请将--output选项传递给docker build 命令。该--output标志带有一个参数:主机上要保存文件的目标位置。

以下命令将server目标中的文件导出到主机文件系统上的当前工作目录:

代码语言:javascript
复制
$ docker build --output=. --target=server .

Dockerfile中可添加一个阶段如下:

代码语言:javascript
复制
FROM scratch AS server
  COPY --from=build-server /bin/server /bin/

执行构建

代码语言:javascript
复制
docker build  --output=./test --target=binaries .

2.3 编写Dockerfile

  • arm
代码语言:javascript
复制
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 /

执行构建

代码语言:javascript
复制
docker build  --output=./test --target=binaries .

此时宿主机当前目录的test下出现ipm二进制文件,实现arm版本打包

  • mips64打包

修改Dockerfile

代码语言:javascript
复制
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 /

执行构建

代码语言:javascript
复制
docker build  --output=./test --target=binaries .

验证

代码语言:javascript
复制
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`时传入参数来打包不同架构镜像

代码语言:javascript
复制
# 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 构建时
代码语言:javascript
复制
docker build -t ipm-arm:v4.0.0 --platform=linux/arm64 .
  • mips
代码语言:javascript
复制
docker build -t ipm-mips:v4.0.0 --platform=linux/mips64le .
  • x86_64
代码语言:javascript
复制
docker build -t ipm-amd:v4.0.0 --platform=linux/amd64 .

在Linux 多平台支持

代码语言:javascript
复制
vim /etc/docker/daemon.json

添加以下内容

代码语言:javascript
复制
{
  "experimental": true, //低版本docker时需要添加此行
  "features": {
    "containerd-snapshotters": true
  }
}

重启docker服务

代码语言:javascript
复制
systemctl daemon-reload
systemctl restart docker.service

安装模拟器

代码语言:javascript
复制
apt-get install qemu qemu-user-static binfmt-support

老版本docker中,如果Dockerfile from的镜像已经在amd机器上存在,则不会去下载arm64镜像,打包出的镜像是amd64的。需要先下载对应平台的基础镜像,再使用docker build --platform=linux/arm64

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-09-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编码如写诗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.1 交叉编译的二进制文件
  • 1.2 多平台架构镜像
  • 基于Docker的交叉编译
    • 2.1 镜像获取
      • 下载和重命名镜像
    • 2.2 导出文件知识
      • 2.3 编写Dockerfile
      • 打包多平台镜像
        • 3.1 修改Dockerfile,使不同平台共用一个。
          • 3.2 构建
          • 在Linux 多平台支持
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档