Docker大学生看了都会系列(九、Docker使用Buildx构建不同CPU架构镜像)

系列文章目录
第一章 Docker介绍
第二章 2.1 Mac通过Homebrew安装Docker
第二章 2.2 CentOS安装Docker
第三章 Docker常用命令
第四章 常用命令实战
第五章 Docker镜像详解
第六章 Docker容器数据卷
第七章 Dockerfile详解
第八章 Dokcerfile部署go项目
第九章 Docker使用Buildx构建不同CPU架构镜像
第十章 Docker网络
第十一章 Docker-Compose用法



一、前言

在上一篇Dokcerfile部署go项目中,只讲到了在本机部署使用,实际商业需求,都需要上传到服务器。不同的服务器架构不一样。为了解决这个需求,所以需要用到Docker Buildx。

二、环境

名称备注
MackBook Pro2023年
芯片Apple M2 Pro(arm64)
macOSSonoma 14.5
操作命令对象Docker 版本26.1.3
简单go项目Go 版本1.22.2

三、Buildx 基本介绍

3.1 什么是Buildx

buildx 是 Docker 官方提供的一个构建工具,它可以帮助用户快速、高效地构建 Docker 镜像,并支持多种平台的构建。使用 buildx,用户可以在单个命令中构建多种架构的镜像,例如 x86 和 ARM 架构,而无需手动操作多个构建命令。此外,buildx 还支持 Dockerfile 的多阶段构建和缓存,这可以大大提高镜像构建的效率和速度。要安装并使用 buildx,需要 Docker Engine 版本号大于等于 19.03。如果你使用的是 Docker Desktop,则默认安装了 buildx。可以使用 docker buildx version 命令查看安装版本,得到以下类似输出,证明已经安装过了。

3.2 Buildx常见命令

更多命令可以通过--help去查找

# 查看buildx的帮助指令
docker buildx --help
# 查看当前的builder实例
docker buildx ls
# 创建新的builder实例
docker buildx create --name [NAME]
# 切换到指定的builder实例
docker buildx use [NAME]
# 检查当前builder实例确保该实例已经启动
docker buildx inspect [NAME] --bootstrap
# 开始构建镜像
docker buildx build [NAME]
# 停止builder实例
docker buildx stop [NAME]
# 删除builder实例
docker buildx rm [NAME]

四、创建builder实例流程

4.1 创建builder实例

docker buildx create --use --name mybuilder

这时候通过docker buildx ls,可以看到刚创建的mybuilder实例的状态还是inactive

4.2 启动builder实例

inspect 子命令用来检查构建器状态,--bootstrap 参数则可以启动 mybuilder构建器

docker buildx inspect --bootstrap mybuilder

4.3 查看builder实例状态

再次通过docker buildx ls,可以看到mybuilder实例的状态是running

五、go项目案例

这里还是以上一篇Dokcerfile部署go项目gindemo项目为例,更具体的代码解释,安装过程请查看上一篇章。

5.1 config.yaml文件

mysql:
  url: 127.0.0.1
  port: 3306

5.2 main.go文件

package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"gopkg.in/yaml.v3"
	"os"
)

type Config struct {
	Mysql Mysql `json:"mysql"`
}

type Mysql struct {
	Url  string
	Port int
}

func main() {
	dataBytes, err := os.ReadFile("config.yaml")
	if err != nil {
		fmt.Println("读取文件失败:", err)
		return
	}
	config := Config{}
	err = yaml.Unmarshal(dataBytes, &config)
	if err != nil {
		fmt.Println("解析 yaml 文件失败:", err)
		return
	}

	r := gin.Default()
	r.GET("/", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"Mysql": config.Mysql,
		})
	})
	r.Run(":8080")
}

六、Dockerfile文件

6.1 完整的Dockerfile文件

#Go版本,最好跟本地(本机电脑)版本一样
ARG GO_VERSION=1.22.4
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS builder
ARG TARGETOS
ARG TARGETARCH
#donkor是我的名字
LABEL author="donkor"

ENV GOPROXY=https://goproxy.cn,direct \
    GOOS=$TARGETOS \
    GO111MODULE=auto \
    GOARCH=$TARGETARCH
#设置国内软件仓库镜像
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

#alpine 基础镜像中没有包含时区信息文件 所以需要安装tzdata
RUN apk update --no-cache && apk add --no-cache tzdata
#设置工作目录
WORKDIR /build
#拷贝当前所有文件到build目录
COPY . .
#安装go项目依赖
RUN go mod download

#-ldflags="-s -w" -w为去掉调试信息(无法使用gdb调试),-s为去掉符号表。 -o 编译输出的名称,代替默认的包名
RUN go build -ldflags="-s -w" -o /build/main


#FROM scratch
FROM --platform=$TARGETPLATFORM scratch
#设置时区
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
ENV TZ Asia/Shanghai

WORKDIR /app
#拷贝编译后的二进制文件
COPY --from=builder /build/main .
#设置数据卷
VOLUME ["/app/config.yaml"]
#暴漏的端口
EXPOSE 8080
#运行程序
ENTRYPOINT ["/app/main"]

6.2 dockerfile中的环境变量

BuildKit 提供的全局变量

名称备注
BUILDPLATFORM构建节点的平台信息,例如linux/amd64、linux/arm64
TARGETOS操作系统,例如linux
TARGETARCH架构,例如amd64、arm64
TARGETPLATFORM构建镜像的目标平台,例如scratch、centos

Go 提供的全局变量

名称备注
GO_VERSIONgo版本,我们自己定义的常量
GOPROXY代理设置
GOOS操作系统
GO111MODULE环境变量
GOARCH架构

6.3 构建过程说明

构建过程分为两个阶段:

1、在一阶段中,我们将拉取一个和当前构建节点相同平台的 golang 镜像,并使用 Go 的交叉编译特性将其编译为目标架构的二进制文件
2、然后拉取目标平台的 scratch 镜像,并将上一阶段的编译结果拷贝到镜像中

七、 构建不同CPU架构镜像

7.1 构建本地镜像

docker buildx build --platform ${BUILDPLATFORM} -f Dockerfile  -t ${imgname}:${imgversion} . --load 

BUILDPLATFORM:构建节点的平台信息,例如linux/amd64、linux/arm64
--load 将镜像保存的本地主机
--push 提交到远程仓库 DockerHub

7.2 保存镜像存成tar 归档文件

docker save -o  filename.tar ${imgname}:${imgversion}

到这里,完整的构建不同CPU架构镜像的流程就完结了

八、拓展,写个shell文件

新建 buildimage.sh文件,智能化构建不同CPU镜像。只需要在终端中执行sh buildimage.sh
完整流程:
1、输入镜像名称。一般为项目名称
2、输入版本号。我比较喜欢写v1,v2,v3…
3、选择操作系统。比如linux/arm64、linux/amd64
4、选择是否推送到阿里云

完整代码

author='donkor'
read -r -p "请输入镜像名称(默认为gindemo): " imgname
#-z字符串为空时
if [[ -z "$imgname" ]]; then
  imgname="${author}/gindemo"
fi
read -r -p "请输入版本号(默认为v1): " imgversion
# -z字符串为空时
if [[ -z "$imgversion" ]]; then
  imgversion="v1"
fi
#可选择的操作系统
#linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
printf "请选择操作系统编号(默认使用linux/arm64)\n1.linux/arm64\n2.linux/amd64\n: "
read -r -n 1 buildplatform
if [[ ${buildplatform} -eq 1 ]];then
   buildplatform="linux/arm64"
elif [[ ${buildplatform} -eq 2 ]]; then
  buildplatform="linux/amd64"
else
  buildplatform="linux/arm64"
fi
#删除镜像
rm -f ${imgname}_${imgversion}_${buildplatform:6}.tar
echo "删除本地镜像完成"
#--load 将镜像保存的本地主机
#--push 提交到远程仓库 DockerHub
docker buildx build --platform ${buildplatform} -f Dockerfile  -t ${imgname}:${imgversion} . --load
docker save -o  ${imgname:7}_${imgversion}_${buildplatform:6}.tar ${imgname}:${imgversion}
echo "构建完成"
echo "镜像操作系统:${buildplatform}"
echo "指定镜像名称:${imgname}:${imgversion}"
echo "本地tar名称:${imgname:7}_${imgversion}_${buildplatform:6}.tar"

printf "是否推送到阿里云(默认不推送)\n0.不推送\n1.推送\n: "
read -r -n 1 push_aliyun
if [[ ${push_aliyun} -eq 1 ]];then
   docker login --username=xx --password=yy registry.cn-shenzhen.aliyuncs.com
   docker tag ${imgname}:${imgversion} registry.cn-shenzhen.aliyuncs.com/donkor/aa:${imgversion}
   docker push registry.cn-shenzhen.aliyuncs.com/donkor/aa:${imgversion}
fi

没有太复杂的东西,sh文件也不是通用的,看看注释改一下成为自己的,就可以用了。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值