Abel'Blog

我干了什么?究竟拿了时间换了什么?

0%

go-发布版本

记录golang项目发布相关的知识点;

在 Golang 程序中,可以通过 ldflags 在编译阶段将发布版本、编译时间等信息注入到程序中。以下是实现的具体步骤:

  1. 定义变量用于存储信息

在代码中定义一组变量来存储版本信息,例如版本号、构建时间、Git 提交哈希等:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
)

// 定义变量,值在编译时通过 -ldflags 注入
var (
Version string
BuildTime string
GitCommit string
)

func main() {
fmt.Printf("Version: %s\n", Version)
fmt.Printf("Build Time: %s\n", BuildTime)
fmt.Printf("Git Commit: %s\n", GitCommit)
}
  1. 编译时注入信息

使用 go build 的 -ldflags 选项注入这些变量的值。例如:

go build -ldflags "-X 'main.Version=v1.0.0' -X 'main.BuildTime=$(date +'%Y-%m-%d %H:%M:%S')' -X 'main.GitCommit=$(git rev-parse HEAD)'" -o myapp

参数说明:

  1. -X ‘main.Version=v1.0.0’:将 main.Version 设置为 v1.0.0。
  2. -X ‘main.BuildTime=$(date +’%Y-%m-%d %H:%M:%S’)’:将 main.BuildTime 设置为当前时间。
  3. -X ‘main.GitCommit=$(git rev-parse HEAD)’:将 main.GitCommit 设置为当前的 Git 提交哈希。

注意: main.Version 等变量的名称需要包含包名(这里是 main),否则 -ldflags 无法找到它们。

  1. 示例输出

假设使用上述命令编译完成后,运行程序会输出类似以下内容:

1
2
3
Version: v1.0.0
Build Time: 2024-12-16 10:30:45
Git Commit: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0
  1. 自动化编译脚本

可以通过脚本简化这个过程,比如使用 Makefile 或 Shell 脚本。

示例 1:使用 Shell 脚本

创建一个 build.sh:

1
2
3
4
5
6
7
8
9
#!/bin/bash

VERSION="v1.0.0"
BUILD_TIME=$(date +'%Y-%m-%d %H:%M:%S')
GIT_COMMIT=$(git rev-parse HEAD)

go build -ldflags "-X 'main.Version=${VERSION}' -X 'main.BuildTime=${BUILD_TIME}' -X 'main.GitCommit=${GIT_COMMIT}'" -o myapp

echo "Build finished: myapp"

运行脚本:

1
build.sh

示例 2:使用 Makefile

创建一个 Makefile:

1
2
3
4
5
6
VERSION := v1.0.0
BUILD_TIME := $(shell date +'%Y-%m-%d %H:%M:%S')
GIT_COMMIT := $(shell git rev-parse HEAD)

build:
go build -ldflags "-X 'main.Version=$(VERSION)' -X 'main.BuildTime=$(BUILD_TIME)' -X 'main.GitCommit=$(GIT_COMMIT)'" -o myapp

运行 make:

make build

  1. 使用 Goreleaser 自动化版本管理(可选)

如果需要更复杂的版本发布管理,可以使用 Goreleaser 工具。它可以自动处理版本信息注入、构建二进制文件、生成发布包等任务。

安装 Goreleaser

1
2
3
brew install goreleaser
# 或使用 go 安装
go install github.com/goreleaser/goreleaser@latest

配置 .goreleaser.yml

1
2
3
4
project_name: myapp
builds:
- ldflags:
- "-X 'main.Version={{.Version}}' -X 'main.BuildTime={{.Date}}' -X 'main.GitCommit={{.Commit}}'"

然后运行:

goreleaser build --snapshot --clean

总结

通过 -ldflags 注入变量是 Golang 编译时实现版本信息管理的最直接方法。使用脚本或 Makefile 可以进一步简化这个过程,而对于复杂的发布流程,Goreleaser 是一个非常方便的工具。

好的!下面是一套完整的 Golang 项目 Docker Compose 发布方案,包含 Dockerfile、docker-compose.yml 配置,以及如何运行和发布你的项目的详细说明。

项目目录结构

假设你的项目目录如下:

my-golang-project/
├── Dockerfile # Docker 构建配置文件
├── docker-compose.yml # Docker Compose 配置文件
├── main.go # 主程序文件
├── build.sh # 构建脚本 (可选)
├── config/ # 配置文件夹 (例如 YAML、JSON 等)
│ └── app.yaml
└── go.mod # Go 模块文件

步骤 1:创建 Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Dockerfile 是用于构建 Golang 项目的镜像的文件。以下是一个通用的配置:

Dockerfile

# 使用官方 Golang 镜像作为构建环境
FROM golang:1.20 AS builder

# 设置工作目录
WORKDIR /app

# 将项目的 go.mod 和 go.sum 文件复制到镜像
COPY go.mod go.sum ./

# 下载依赖
RUN go mod download

# 将项目文件复制到镜像
COPY . .

# 使用 -ldflags 构建二进制文件,将版本等信息打包进去
ARG VERSION=dev
ARG BUILD_TIME=unknown
ARG GIT_COMMIT=none
RUN go build -ldflags "-X 'main.Version=${VERSION}' -X 'main.BuildTime=${BUILD_TIME}' -X 'main.GitCommit=${GIT_COMMIT}'" -o app .

# 构建一个最小的运行时镜像
FROM debian:bullseye-slim

# 设置工作目录
WORKDIR /app

# 从构建阶段复制可执行文件
COPY --from=builder /app/app /app/app

# 复制配置文件到运行时镜像
COPY config /app/config

# 暴露服务端口
EXPOSE 8080

# 启动服务
CMD ["./app"]

步骤 2:创建 docker-compose.yml

示例 docker-compose.yml

以下是 docker-compose.yml 的模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
version: "3.9"

services:
golang-app:
build:
context: .
dockerfile: Dockerfile
args:
VERSION: "1.0.0" # 设置版本
BUILD_TIME: "${BUILD_TIME:-$(date)}"
GIT_COMMIT: "${GIT_COMMIT:-$(git rev-parse HEAD)}"
container_name: golang-app
ports:
- "8080:8080" # 将容器的 8080 端口映射到主机
volumes:
- ./config:/app/config # 挂载配置文件,方便本地修改
environment:
- ENV=production # 传递环境变量

步骤 3:准备项目代码

示例 main.go

下面是一个简单的 main.go 示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
"fmt"
"net/http"
"os"
)

var (
Version string
BuildTime string
GitCommit string
)

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, Docker Compose!\n")
fmt.Fprintf(w, "Version: %s\nBuild Time: %s\nGit Commit: %s\n", Version, BuildTime, GitCommit)
}

func main() {
port := "8080"
if envPort := os.Getenv("PORT"); envPort != "" {
port = envPort
}

http.HandleFunc("/", handler)

fmt.Printf("Starting server on :%s...\n", port)
if err := http.ListenAndServe(":"+port, nil); err != nil {
fmt.Printf("Error starting server: %s\n", err)
}
}

步骤 4:运行和测试

  1. 构建和运行服务

在项目根目录下运行以下命令:

1
2
# 构建并启动服务
docker-compose up --build

  1. 检查运行状态

确认服务运行正常,可以在浏览器访问 http://localhost:8080,你应该会看到以下输出:

1
2
3
4
Hello, Docker Compose!
Version: 1.0.0
Build Time: 2024-12-16 14:35:00
Git Commit: a1b2c3d4e5f6

可选步骤:优化部署

  1. 添加 .env 文件管理环境变量

创建一个 .env 文件:

1
2
3
VERSION=1.0.0
BUILD_TIME=$(date)
GIT_COMMIT=$(git rev-parse HEAD)

修改 docker-compose.yml 使用 .env:

1
2
3
4
5
build:
args:
VERSION: "${VERSION}"
BUILD_TIME: "${BUILD_TIME}"
GIT_COMMIT: "${GIT_COMMIT}"

  1. 运行在后台

如果不需要查看日志,可以在后台运行:

docker-compose up -d

  1. 停止和清理容器

停止服务:

docker-compose down

清理构建的镜像和卷:

docker-compose down --rmi all --volumes

整体流程总结

  1. 编写代码:在 main.go 中添加功能代码。
  2. 编写 Dockerfile:通过 Dockerfile 构建运行环境和项目镜像。
  3. 编写 docker-compose.yml:定义服务及其依赖项。
  4. 运行服务:使用 docker-compose up 启动和发布。