构建与编译
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 环境变量或 latest | v2.0.0 |
| Git 提交哈希 | git rev-parse --short HEAD | a1b2c3d4 |
| 构建时间 | date -u +%Y-%m-%dT%H:%M:%SZ | 2025-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支持的构建平台:
| 平台 | 架构 |
|---|---|
| Linux | amd64, arm64, armv7 |
| Windows | amd64, arm64 |
| macOS | amd64, arm64 |
| FreeBSD | amd64 |
| OpenBSD | amd64 |
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) 函数按以下优先级取值:
- ldflags 注入值(优先级最高)
- 代码传参 (
main.go中的硬编码兜底) - 运行时 fallback(
time.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 使用多阶段构建,包含三个阶段:
- 前端构建阶段 (
frontend-builder):基于node:24-alpine,构建 Vue 前端 - 后端构建阶段 (
backend-builder):基于golang:1.24-alpine,编译 Go 二进制并注入版本信息 - 运行阶段 (
alpine:latest):仅包含二进制文件和运行时依赖,生成最小镜像
构建参数
Docker 构建时可传递以下 --build-arg 参数:
| 参数 | 说明 | 默认值 |
|---|---|---|
VERSION | 镜像和二进制版本号 | latest |
GIT_COMMIT | Git 提交哈希 | 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 .dataQ: 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