命令与部署
日常只有六条命令:make run-min 起服务、make test-short 跑测试、
make ci 交付前自检。其余目标与部署形态在这页列全。
Makefile 目标
make 不带参数(默认目标 help)会从 Makefile 里抽出所有
带 ## 注释的目标打印出来——下面这张表与它同源。
| 目标 | 做什么 | 什么时候用 |
|---|---|---|
make help | 列出全部目标(默认目标) | 忘了目标名时 |
make build | go build ./...,编译全部包但不产出文件 | 确认改动能编译 |
make bins | 编译 bin/<SERVICE>(默认 demo)与 bin/migrate | 要拿到可执行文件时 |
make run | go 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=http | go run ./examples/$(NAME) | 跑某个能力示例,NAME 取 examples/ 下的目录名 |
make migrate | go run ./cmd/migrate -driver $(DRIVER) -dsn "$(DSN)",默认 DRIVER=postgres | 建表/改表;-driver 可切 mysql / sqlite |
make dev | docker compose -f docker-compose.dev.yml up -d | 本地起 postgres/mysql/redis/memcache/kafka |
make dev-down | 停掉上面的 compose 栈 | 收工 |
make fmt | gofmt -w 全部 *.go(排除 gen/) | 提交前 |
make vet | go vet ./... | 静态检查,比 lint 快 |
make lint | golangci-lint run(含 depguard 一致性守卫) | 本地跑与 CI 相同的 lint;未安装先 make tools |
make test | go test -race -count=1 ./...,全量测试 | 交付前完整验证 |
make test-short | go test -short -race -count=1 ./...,含 sqlite / miniredis / kfake / 进程内 RPC 用例 | 日常改动的首选;仍带竞态检测 |
make cover | 生成 coverage.out 并打开 HTML 覆盖率报告 | 看覆盖缺口 |
make ci | vet + test-short -race + build,与 CI 一致的校验 | 交付前必跑 |
make tools | go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.14.0 | 装 lint,版本与 CI 对齐 |
make tidy | go mod tidy | 增删依赖后 |
make docker TAG=v1 | docker 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
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"]
-
:nonroot:以非 root 用户运行,无 shell、无包管理器, 镜像里没有可被利用的额外工具。 -
-ldflags="-s -w":去掉符号表与调试信息,缩小体积。 -
配置进镜像:
configs/config.min.yaml被复制成/configs/config.yaml,所以镜像开箱即起(只监听 8080,不连任何外部服务)。
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 停掉:
| 服务 | 镜像 | 端口 | 凭据 / 说明 |
|---|---|---|---|
postgres | postgres:16 | 5432 | user/password/db 都是 matex;数据卷 pgdata |
mysql | mysql:8.0 | 3306 | root 密码 matex,库与用户 matex;DSN 记得带 parseTime=true,数据卷 mysqldata |
redis | redis:7 | 6379 | 无密码 |
memcached | memcached:1.6 | 11211 | — |
kafka | bitnami/kafka:3.7 | 9092 | KRaft 单节点(无 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 刻意保留的性质。
下一步
- 目录与约定:代码该放哪、四条强制约定是什么。
- 离线测试:
dbtest/redistest的用法与真库切换。 - examples/lifecycle:优雅退出与就绪门,部署时的探针语义。