系列文章目录
第一章 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 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文件也不是通用的,看看注释改一下成为自己的,就可以用了。