Docker构建跨平台镜像,信创必备,建议收藏备用

由于工作需要,再加上现在信创的火爆,之前单架构(x86)已经满足不了需求了,拥抱 arm 架构已成趋势,第一 arm 架构服务器便宜(以云平台为例,arm 比 x86 便宜30%),第二 arm 架构具有较先进的设计可能性能上更加优秀,总之,拥抱新事物,总会得到新的收获。

我相信大部分公司容器化使用的依然是 docker 吧,docker 镜像构建是容器化的基石,今天我就来带大家熟悉一下 docker 构建跨平台镜像 的玩法。

我的文章喜欢先贴官网权威文档,因为要让大家知道追本溯源,要想学到第一手资料,还是鼓励大家多多尝试阅读官网文档,当然,也不排除官网有时候写的比较浅显,覆盖不了具体的使用场景,实战性不强(外链接跳来跳去抓不住重点)。

https://docs.docker.com/build/building/multi-platform/

大家可以关注我的公*号:新质程序猿,上面有更多好玩精彩的内容哟!

概念

这里所指的跨平台就是指一份代码可以编译运行在多种不同的 cpu 架构下,如 x86(amd), arm 架构,不是指不同的操作系统。

我们所熟知的 java 也宣称的是跨平台的,它其实是指 java 程序可以运行在任何安装了 jvm (java虚拟机)的操作系统上,它最初可能指的是操作系统层面,当然,jvm 也有 arm 架构的适配,也是完全的跨平台的。

交叉编译

目前主流的编程语言基本都是支持交叉编译的,所谓交叉编译是指在一种平台上编译生成另一种平台上可执行的程序,主要有 2 类需求:

  1. 不同操作系统之间的交叉编译,例如在 Windows 上编译生成 Linux 可执行程序

  2. 不同硬件架构之间的交叉编译,例如在 x86 架构上编译生成 ARM 架构可执行程序

不同的编程语言可能需要的相关依赖环境不同,我仅举例我熟悉的几种作为参考,如未覆盖您的技术栈,你可以自行搜索就可以找到相关的资源。

Java

上面也说了,Java 是跨平台的,Java 的跨平台是依托 JVM,所以 Java 直接正常打包编译即可,只需要打成 jar, war 字节码就可以了,不同的平台安装对应平台的 JVM 环境(JRE/JDK)即可。

Golang

golang 不像 Java 拥有 JVM,需要编译多份二进制文件,好在 golang 提供了交叉编译的选项,在golang中,你可以使用 GOOS 和 GOARCH 环境变量来指定目标平台:

# 编译 win/amd64
GOOS=windows GOARCH=amd64 go build -o yourapp.exe
# 编译 mac/amd64
GOOS=darwin GOARCH=amd64 go build -o yourapp_osx
# 编译 linux/arm64
GOOS=linux GOARCH=arm64 go build -o yourapp_arm64

由于 arm 还有不同的版本,golang 还提供了 GOARM 环境变量

# 编译 linux/arm/v7
GOOS=linux GOARCH=arm GOARM=7 go build -o yourapp_armv7
解释性语言

对于一些解释性语言,如 PHP,Python, Lua,HTML/CSS/JS 这一类,压根不需要编译,只要安装对应的环境即可(如安装 Python 环境,安装 PHP 环境,跟Java 类似)

好了,简单普及一下语言本身的交叉编译,回到正题,我们今天的主题是 如何构建跨平台的 容器镜像。

跨平台镜像

大家知道 docker 镜像是一个包含了操作系统核心文件的压缩包,我们在制作服务镜像前,肯定需要找一个基础镜像,如 openjdk, tomcat, centos, nginx 等等,而这些基础镜像除了具有不同的版本之外,还有不同架构,如下图:

https://hub.docker.com/_/python

一般情况下,你在执行 docker pull 的时候,docker 命令会根据你当前架构拉取对应的 OS/ARCH 的版本,如下执行 docker version 会列出 OS/Arch 信息。

# docker version
Client: Docker Engine - Community
 ....
 OS/Arch:           linux/amd64
 ....

Server: Docker Engine - Community
 Engine:
  ....
  OS/Arch:          linux/amd64
  ....

构建镜像

为了直观的演示镜像构建,我们一步步的依据一个最简单的 golang 程序来进行实操(下文也会用到这 2 个文件)。

代码就一个文件 main.go

package main
 
import (
    "fmt"
    "runtime"
)
 
func main() {
    fmt.Println("Hello world!")
    fmt.Printf("Running in [%s] architecture.\n", runtime.GOARCH)
}

Dockerfile, 采用 2 步构建法

FROM golang:1.18 as builder

WORKDIR /app
COPY main.go /app/main.go
RUN go build -a -o output/main main.go

FROM alpine:latest
WORKDIR /root
COPY --from=builder /app/output/main .
CMD /root/main

amd64构建

在 amd64 机器(也就是x86_64机器)执行构建并运行

# 构建 test 镜像
docker build -t test .
# 输出
[+] Building 12.5s (13/13) FINISHED                                                                                                                                                                                  docker:default
 => [internal] load build definition from Dockerfile                                                                                                                                                                           0.4s
 => => transferring dockerfile: 234B                                                                                                                                                                                           0.1s
 => [internal] load metadata for docker.io/library/golang:1.18                                                                                                                                                                 0.0s
 =&g
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值