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

Donkor- 2024-07-01 14:37:12 阅读 77

系列文章目录

第一章 Docker介绍

第二章 2.1 Mac通过Homebrew安装Docker

第二章 2.2 CentOS安装Docker

第三章 Docker常用命令

第四章 常用命令实战

第五章 Docker镜像详解

第六章 Docker容器数据卷

第七章 Dockerfile详解

第八章 Dokcerfile部署go项目

第九章 Docker使用Buildx构建不同CPU架构镜像

第十章 Docker网络

第十一章 Docker-Compose用法


文章目录

一、前言二、环境三、Buildx 基本介绍3.1 什么是Buildx3.2 Buildx常见命令

四、创建builder实例流程4.1 创建builder实例4.2 启动builder实例4.3 查看builder实例状态

五、go项目案例5.1 config.yaml文件5.2 main.go文件

六、Dockerfile文件6.1 完整的Dockerfile文件6.2 dockerfile中的环境变量6.3 构建过程说明

七、 构建不同CPU架构镜像7.1 构建本地镜像7.2 保存镜像存成tar 归档文件

八、拓展,写个shell文件


一、前言

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

二、环境

名称 备注
MackBook Pro 2023年
芯片 Apple M2 Pro(arm64)
macOS Sonoma 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_VERSION go版本,我们自己定义的常量
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文件也不是通用的,看看注释改一下成为自己的,就可以用了。



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。