系列文章目录
第一章 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/arm64TARGETOS操作系统,例如linuxTARGETARCH架构,例如amd64、arm64TARGETPLATFORM构建镜像的目标平台,例如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"]];thenimgname="${author}/gindemo"firead-r-p"请输入版本号(默认为v1): " imgversion
# -z字符串为空时if[[-z"$imgversion"]];thenimgversion="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/v6printf"请选择操作系统编号(默认使用linux/arm64)\n1.linux/arm64\n2.linux/amd64\n: "read-r-n1 buildplatform
if[[${buildplatform}-eq1]];thenbuildplatform="linux/arm64"elif[[${buildplatform}-eq2]];thenbuildplatform="linux/amd64"elsebuildplatform="linux/arm64"fi#删除镜像rm-f${imgname}_${imgversion}_${buildplatform:6}.tar
echo"删除本地镜像完成"#--load 将镜像保存的本地主机#--push 提交到远程仓库 DockerHubdocker buildx build --platform${buildplatform}-f Dockerfile -t${imgname}:${imgversion}.--loaddocker 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-n1 push_aliyun
if[[${push_aliyun}-eq1]];thendocker 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文件也不是通用的,看看注释改一下成为自己的,就可以用了。
版权归原作者 Donkor- 所有, 如有侵权,请联系我们删除。