Skip to content

构建与编译

DNS-Go 支持多种构建方式,并实现了构建时信息注入(-ldflags -X),在编译时将版本号、Git 提交哈希和构建时间注入到 Go 二进制中。

构建方式

方式一:Docker 构建(推荐)

使用项目根目录下的 build-docker.sh 脚本进行 Docker 镜像构建:

bash
# 默认版本(latest)
./build-docker.sh

# 指定版本
VERSION=v2.0.0 ./build-docker.sh

# 构建并推送到仓库
./build-docker.sh push

# 指定镜像名称
IMAGE_NAME=my-registry/dns-go VERSION=v2.0.0 ./build-docker.sh

构建过程会自动注入以下信息:

注入变量来源示例值
版本号VERSION 环境变量或 latestv2.0.0
Git 提交哈希git rev-parse --short HEADa1b2c3d4
构建时间date -u +%Y-%m-%dT%H:%M:%SZ2025-01-15T10:00:00Z

Windows 用户 使用 build-docker.bat

batch
build-docker.bat
build-docker.bat push

方式二:Python 交叉编译

使用 build.py 脚本进行多平台交叉编译:

bash
# 安装依赖
pip install loguru

# 构建当前平台
python build.py

# 构建指定平台
python build.py -p linux-amd64 windows-amd64

# 构建所有支持平台
python build.py --all

# 指定输出目录
python build.py -o ./dist

支持的构建平台:

平台架构
Linuxamd64, arm64, armv7
Windowsamd64, arm64
macOSamd64, arm64
FreeBSDamd64
OpenBSDamd64

Python 构建脚本会从环境变量或自动获取以下信息注入二进制:

bash
# 也可以显式指定
VERSION=v2.0.0 GIT_COMMIT=a1b2c3d4 BUILD_DATE=2025-01-15T10:00:00Z python build.py

方式三:直接 Go 编译

bash
# 不带 ldflags(使用代码中的默认值)
go build -o dns-go-app ./backend/cmd/main.go

# 带 ldflags 注入版本信息
go build -ldflags "\
  -X 'gitee.com/liumou_site/dns-go/backend/pkg.buildVersion=v2.0.0' \
  -X 'gitee.com/liumou_site/dns-go/backend/pkg.buildCommit=a1b2c3d4' \
  -X 'gitee.com/liumou_site/dns-go/backend/pkg.buildTime=2025-01-15T10:00:00Z'" \
  -o dns-go-app ./backend/cmd/main.go

构建时信息注入原理

DNS-Go 通过 Go 的 -ldflags -X 机制在编译时注入构建信息。

注入变量

这些变量定义在 backend/pkg/version.go 中:

go
var (
    buildVersion = "" // 版本号
    buildCommit  = "" // Git 提交哈希
    buildTime    = "" // 构建时间
)

优先级规则

SetVersion(version, gitCommit) 函数按以下优先级取值:

  1. ldflags 注入值(优先级最高)
  2. 代码传参main.go 中的硬编码兜底)
  3. 运行时 fallbacktime.Now() 作为最终保障)
go
func SetVersion(version, gitCommit string) {
    // 如果 ldflags 注入了值(非空字符串),则覆盖代码传参
    if buildVersion != "" {
        version = buildVersion
    }
    // ...
}

查看构建信息

编译完成后,启动服务,通过系统信息接口可以查看注入的构建信息:

bash
# 查看系统信息(含构建时间)
curl http://localhost:8085/api/system/info

# 响应示例
{
  "systemName": "DNS-Go",
  "version": "v2.0.0",
  "gitCommit": "a1b2c3d4",
  "buildTime": "2025-01-15T10:00:00Z",
  "goVersion": "go1.24.0",
  "os": "linux",
  "arch": "amd64",
  "hostname": "server-01",
  "startTime": "2025-01-15T10:30:00"
}

也可以在 Web 管理界面的 关于系统 页面查看这些信息。

多阶段 Docker 构建

Dockerfile 使用多阶段构建,包含三个阶段:

  1. 前端构建阶段 (frontend-builder):基于 node:24-alpine,构建 Vue 前端
  2. 后端构建阶段 (backend-builder):基于 golang:1.24-alpine,编译 Go 二进制并注入版本信息
  3. 运行阶段 (alpine:latest):仅包含二进制文件和运行时依赖,生成最小镜像

构建参数

Docker 构建时可传递以下 --build-arg 参数:

参数说明默认值
VERSION镜像和二进制版本号latest
GIT_COMMITGit 提交哈希unknown
BUILD_DATE构建时间(ISO 8601 格式)当前时间
TARGETPLATFORM目标平台(buildx 自动填充)当前主机平台

常见问题

Q: 不传 ldflags 会怎样?

二进制依然可以正常运行。buildVersion/buildCommit/buildTime 默认为空字符串时,SetVersion() 会使用代码中传递的参数值,BuildTime 最终由 time.Now() 在运行时生成。

Q: 如何验证构建信息已成功注入?

bash
# 编译后查看二进制中包含的版本字符串
strings dns-go-app | grep -E "buildVersion|buildCommit|buildTime"

# 或启动服务后查看系统信息
curl http://localhost:8085/api/system/info | jq .data

Q: Python 构建时如何指定版本?

bash
# 通过环境变量传递
VERSION=v2.0.0 GIT_COMMIT=$(git rev-parse --short HEAD) python build.py

# 或在 VERSION 文件中写入版本号
echo "v2.0.0" > VERSION
python build.py

相关文档

基于 MIT 许可发布