feat(docker): 支持通过构建参数注入编译时间

在 Dockerfile 中添加 BUILD_DATE 构建参数,并通过 ldflags 将编译时间注入到二进制文件中。
同时更新 build.sh 脚本,在构建镜像时传入当前时间作为 BUILD_DATE 参数。

refactor(build): 优化 build.sh 脚本结构与可读性

对 build.sh 脚本中的函数进行了缩进统一和结构调整,提高代码可读性和维护性。
新增 bin 命令用于直接编译并压缩二进制文件。

feat(main): 添加版本与构建信息显示功能

在 main.go 中增加 BuildDate 变量用于存储构建时间,并支持通过 -h 或 --help 参数查看帮助信息,
包括版本号、联系邮箱以及构建日期等元数据。

chore(blacklist): 移除默认黑名单条目

从 blacklist.txt 文件中移除默认的 *.baidu.com 黑名单规则。

docs(readme): 清理 README.md 文件末尾空行

删除 README.md 文件最后多余的空白行,保持文档整洁。
This commit is contained in:
2025-10-15 15:16:09 +08:00
parent 4060e83686
commit 3cf657bb62
6 changed files with 79 additions and 47 deletions

View File

@@ -4,8 +4,10 @@ FROM golang:1.25.2-alpine AS builder
WORKDIR /app WORKDIR /app
COPY . . COPY . .
# 使用构建参数传递编译时间
ARG BUILD_DATE
ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64 ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
RUN go build -o dot main.go RUN go build -a -ldflags "-X main.BuildDate=${BUILD_DATE} -extldflags '-static -lc'"
# ---------- 运行阶段 ---------- # ---------- 运行阶段 ----------
FROM alpine:3.20 FROM alpine:3.20

View File

@@ -159,4 +159,3 @@ kdig @127.0.0.1 +tls-ca +tls-host=dot.local www.example.com
**Email:** [aixiao@aixiao.me](mailto:aixiao@aixiao.me) **Email:** [aixiao@aixiao.me](mailto:aixiao@aixiao.me)
**License:** MIT **License:** MIT
**Repository:** [git.aixiao.me/aixiao/dot](https://git.aixiao.me/aixiao/dot) **Repository:** [git.aixiao.me/aixiao/dot](https://git.aixiao.me/aixiao/dot)

View File

@@ -1 +0,0 @@
*.baidu.com

101
build.sh
View File

@@ -27,70 +27,83 @@ KEY_FILE="jinllpay.com.key"
# ---------- 函数区 ---------- # ---------- 函数区 ----------
build() { build() {
echo "🔨 Building Docker image: ${IMAGE_NAME}:${TAG} ..." echo "🔨 Building Docker image: ${IMAGE_NAME}:${TAG} ..."
docker build -t "${IMAGE_NAME}:${TAG}" . docker build --build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
echo "✅ Build complete." -t "${IMAGE_NAME}:${TAG}" .
echo "✅ Build complete."
} }
run() { run() {
echo "🚀 Starting container ${CONTAINER_NAME}..." echo "🚀 Starting container ${CONTAINER_NAME}..."
# 确保旧容器不冲突 # 确保旧容器不冲突
if docker ps -a --format '{{.Names}}' | grep -w "${CONTAINER_NAME}" >/dev/null 2>&1; then if docker ps -a --format '{{.Names}}' | grep -w "${CONTAINER_NAME}" >/dev/null 2>&1; then
echo "⚠️ Existing container found. Removing..." echo "⚠️ Existing container found. Removing..."
docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1 || true docker rm -f "${CONTAINER_NAME}" >/dev/null 2>&1 || true
fi fi
docker run -d \ docker run -d \
--name "${CONTAINER_NAME}" \ --name "${CONTAINER_NAME}" \
--memory=256m \ --memory=256m \
--memory-swap=384m \ --memory-swap=384m \
--memory-reservation=128m \ --memory-reservation=128m \
-p ${PORT}:853 \ -p ${PORT}:853 \
-e CERT_FILE="/app/${CERT_FILE}" \ -e CERT_FILE="/app/${CERT_FILE}" \
-e KEY_FILE="/app/${KEY_FILE}" \ -e KEY_FILE="/app/${KEY_FILE}" \
-v "$(pwd)/${CERT_FILE}:/app/${CERT_FILE}:ro" \ -v "$(pwd)/${CERT_FILE}:/app/${CERT_FILE}:ro" \
-v "$(pwd)/${KEY_FILE}:/app/${KEY_FILE}:ro" \ -v "$(pwd)/${KEY_FILE}:/app/${KEY_FILE}:ro" \
"${IMAGE_NAME}:${TAG}" "${IMAGE_NAME}:${TAG}"
echo "✅ Container started on port ${PORT}." echo "✅ Container started on port ${PORT}."
} }
logs() { logs() {
echo "📜 Showing logs..." echo "📜 Showing logs..."
docker logs -f "${CONTAINER_NAME}" docker logs -f "${CONTAINER_NAME}"
} }
stop() { stop() {
echo "🛑 Stopping container..." echo "🛑 Stopping container..."
docker stop "${CONTAINER_NAME}" >/dev/null 2>&1 || true docker stop "${CONTAINER_NAME}" >/dev/null 2>&1 || true
docker rm "${CONTAINER_NAME}" >/dev/null 2>&1 || true docker rm "${CONTAINER_NAME}" >/dev/null 2>&1 || true
echo "✅ Container stopped and removed." echo "✅ Container stopped and removed."
} }
clean() { clean() {
stop stop
echo "🧹 Removing image ${IMAGE_NAME}:${TAG}..." echo "🧹 Removing image ${IMAGE_NAME}:${TAG}..."
docker rmi "${IMAGE_NAME}:${TAG}" >/dev/null 2>&1 || true docker rmi "${IMAGE_NAME}:${TAG}" >/dev/null 2>&1 || true
echo "✅ Cleanup complete." echo "✅ Cleanup complete."
} }
rebuild() { rebuild() {
clean clean
build build
run run
}
bin() {
DATE=$(date "+%Y-%m-%dT%H:%M:%S")
a="'"
eval "CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -a -ldflags ${a}-X main.BuildDate=${DATE} -extldflags \"-static -lc\"${a}"
if test -f dot; then
upx -9 dot
fi
} }
# ---------- 主逻辑 ---------- # ---------- 主逻辑 ----------
case "$1" in case "$1" in
build) build ;; bin) bin ;;
run) run ;; build) build ;;
logs) logs ;; run) run ;;
stop) stop ;; logs) logs ;;
clean) clean ;; stop) stop ;;
rebuild) rebuild ;; clean) clean ;;
*) rebuild) rebuild ;;
echo "Usage: ./build.sh [build|run|logs|stop|clean|rebuild]" *)
exit 1 echo "Usage: ./build.sh [build|run|logs|stop|clean|rebuild]"
;; exit 1
;;
esac esac

BIN
dot

Binary file not shown.

19
main.go
View File

@@ -19,6 +19,8 @@ import (
lru "github.com/hashicorp/golang-lru/v2" lru "github.com/hashicorp/golang-lru/v2"
) )
var BuildDate = "unknown" // 由编译时注入
/****************************************************************** /******************************************************************
* 日志初始化 * 日志初始化
******************************************************************/ ******************************************************************/
@@ -571,6 +573,7 @@ func handleDNS(
func main() { func main() {
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
var help bool
certFile := flag.String("cert", "server.crt", "TLS 证书文件路径") certFile := flag.String("cert", "server.crt", "TLS 证书文件路径")
keyFile := flag.String("key", "server.key", "TLS 私钥文件路径") keyFile := flag.String("key", "server.key", "TLS 私钥文件路径")
addr := flag.String("addr", ":853", "DoT 监听地址") addr := flag.String("addr", ":853", "DoT 监听地址")
@@ -585,8 +588,24 @@ func main() {
blacklistFile := flag.String("blacklist-file", "", "黑名单文件路径(每行一个域名;支持 # 或 ; 注释;后缀匹配)") blacklistFile := flag.String("blacklist-file", "", "黑名单文件路径(每行一个域名;支持 # 或 ; 注释;后缀匹配)")
blacklistRcodeFlag := flag.String("blacklist-rcode", "REFUSED", "命中黑名单返回的 RCODEREFUSED|NXDOMAIN|SERVFAIL") blacklistRcodeFlag := flag.String("blacklist-rcode", "REFUSED", "命中黑名单返回的 RCODEREFUSED|NXDOMAIN|SERVFAIL")
verbose := flag.Bool("v", false, "verbose 日志") verbose := flag.Bool("v", false, "verbose 日志")
flag.BoolVar(&help, "h", false, "")
flag.BoolVar(&help, "help", false, "帮助信息")
flag.Parse() flag.Parse()
if help {
fmt.Printf(
"\t\tDNS-over-TLS (DoT)\n"+
"\tVersion 0.1\n"+
"\tE-mail: aixiao@aixiao.me\n"+
"\tBuild Date: %s\n", BuildDate)
flag.Usage()
fmt.Printf("\n")
os.Exit(0)
}
initLogger(*verbose) initLogger(*verbose)
var err error var err error