命令与部署

日常只有六条命令:make run-min 起服务、make test-short 跑测试、 make ci 交付前自检。其余目标与部署形态在这页列全。

Makefile 目标

make 不带参数(默认目标 help)会从 Makefile 里抽出所有 带 ## 注释的目标打印出来——下面这张表与它同源。

目标 做什么 什么时候用
make help列出全部目标(默认目标)忘了目标名时
make buildgo build ./...,编译全部包但不产出文件确认改动能编译
make bins编译 bin/<SERVICE>(默认 demo)与 bin/migrate要拿到可执行文件时
make rungo run ./cmd/$(SERVICE) -conf configs/config.yaml用完整配置跑(需要 db/redis 等已就绪)
make run-min用 configs/config.min.yaml 跑,零依赖只想看服务能不能起
make run-sqlite用 configs/config.sqlite.yaml 跑(纯 Go SQLite)要数据库但不想起 Docker,需先 make migrate DRIVER=sqlite DSN=file:matex.db
make example NAME=httpgo run ./examples/$(NAME)跑某个能力示例,NAME 取 examples/ 下的目录名
make migratego run ./cmd/migrate -driver $(DRIVER) -dsn "$(DSN)",默认 DRIVER=postgres建表/改表;-driver 可切 mysql / sqlite
make devdocker compose -f docker-compose.dev.yml up -d本地起 postgres/mysql/redis/memcache/kafka
make dev-down停掉上面的 compose 栈收工
make fmtgofmt -w 全部 *.go(排除 gen/)提交前
make vetgo vet ./...静态检查,比 lint 快
make lintgolangci-lint run(含 depguard 一致性守卫)本地跑与 CI 相同的 lint;未安装先 make tools
make testgo test -race -count=1 ./...,全量测试交付前完整验证
make test-shortgo test -short -race -count=1 ./...,含 sqlite / miniredis / kfake / 进程内 RPC 用例日常改动的首选;仍带竞态检测
make cover生成 coverage.out 并打开 HTML 覆盖率报告看覆盖缺口
make civet + test-short -race + build,与 CI 一致的校验交付前必跑
make toolsgo install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.14.0装 lint,版本与 CI 对齐
make tidygo mod tidy增删依赖后
make docker TAG=v1docker build -t $(SERVICE):latest .打镜像
make clean删除 bin/ 与 coverage.out清理产物
三个变量 SERVICE(默认 demo)决定 run / bins / docker 操作哪个二进制;DRIVER(默认 postgres) 与 DSN 供 migrate 使用;TAG 供 docker 使用。用法如 make migrate DRIVER=sqlite DSN=file:matex.db。

make ci:交付前的自检

ci: ## 与 CI 一致的校验
	go vet ./...
	go test -short -race -count=1 ./...
	go build ./...

三步的顺序与 CI 的 test job 完全一致(CI 的那份见下)。-short 并没有把数据库用例跳掉——matex 的测试基座默认用纯 Go SQLite 与 miniredis, 所以 test-short 在无 Docker、无网络的环境里仍覆盖 DB 路径。 只有需要真实中间件的用例(DB_TEST_DRIVER / DB_TEST_DSN 指向真库的)才留在 make test 里。

GitHub Actions

工作流 .github/workflows/ci.yml,触发条件是所有 push 与 pull_request,两个 job:

Job 步骤
lint actions/checkout@v4 → actions/setup-go@v5(go-version-file: go.mod,开缓存)→ go mod download → golangci/golangci-lint-action@v9,version: v2.14.0
test 同前两步 → go vet ./... → go test -short -race -count=1 ./... → go build ./...

lint 与 test 并行跑,两者都在 ubuntu-latest 上,都不需要 service container——这是"离线可跑"的直接收益:CI 里没有 postgres、没有 redis, 测试照样跑完。make tools 装的 golangci-lint 版本(v2.14.0)与 CI 一致, 避免本地过、CI 不过这类假故障。

Docker 镜像

flowchart LR
    subgraph build["构建阶段 golang:1.27.1-trixie"]
        COPY1["COPY go.mod go.sum
然后 go mod download"] COPY2["COPY . ."] BUILD["CGO_ENABLED=0
go build -ldflags 压缩符号
-o /out/demo ./cmd/demo"] COPY1 --> COPY2 --> BUILD end subgraph run["运行阶段 distroless/static-debian12:nonroot"] BIN["/demo(静态二进制)"] CFG["/configs/config.yaml
来自 configs/config.min.yaml"] EXP["EXPOSE 8080
ENTRYPOINT /demo -conf /configs/config.yaml"] BIN --> EXP CFG --> EXP end BUILD -->|"COPY --from=build"| BIN
多阶段:构建镜像里带完整 Go 工具链,运行镜像只留一个静态二进制加一份最小配置。 CGO_ENABLED=0 是这个组合成立的前提——纯 Go 构建产出的静态二进制 才能跑在 distroless 的 static 镜像上,且 modernc.org/sqlite 不需要 cgo。

关键几行:

FROM golang:1.27.1-trixie AS build
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /out/demo ./cmd/demo

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /out/demo /demo
COPY configs/config.min.yaml /configs/config.yaml
EXPOSE 8080
ENTRYPOINT ["/demo", "-conf", "/configs/config.yaml"]
镜像默认是最小配置 镜像是"配了才建"的:只有配置里出现 db: / redis: / memcache: / kafka: 段,对应基础设施才会被初始化。 因此光给环境变量不会打开 db/redis——必须让 /configs/config.yaml 里存在那些段。接真实依赖时挂一份完整配置覆盖它:
docker run -p 8080:8080 \
  -v "$PWD/configs/config.yaml:/configs/config.yaml:ro" \
  matex:latest
镜像里的配置用 ${DB_DSN:…} 这类占位符,所以仍可由环境变量提供 DSN 等值; 但段的存在与否只能由配置文件决定。

本地依赖:docker-compose.dev.yml

make dev 起这一栈,make dev-down 停掉:

服务 镜像 端口 凭据 / 说明
postgrespostgres:165432user/password/db 都是 matex;数据卷 pgdata
mysqlmysql:8.03306root 密码 matex,库与用户 matex;DSN 记得带 parseTime=true,数据卷 mysqldata
redisredis:76379无密码
memcachedmemcached:1.611211—
kafkabitnami/kafka:3.79092KRaft 单节点(无 Zookeeper);advertised listener 是 localhost:9092

起完依赖之后的典型顺序:

make dev                     # 起 postgres/mysql/redis/memcache/kafka
make migrate DSN=postgres://matex:matex@localhost:5432/matex?sslmode=disable
make run                     # 用 configs/config.yaml 起服务

想拉远端镜像时 make dev 需要网络;但跑测试与跑示例不需要它—— 那是 matex 刻意保留的性质。

下一步