最轻量发布是直接编译二进制,但多环境等场景必须容器化;go build需禁用CGO、指定GOOS=linux并加-s -w参数;Docker多阶段构建要先copy go.mod再copy源码;运行镜像避免scratch而选alpine;Fly.io部署须动态读取PORT、对齐internal_port,并提供/healthz健康检查端点。

直接编译成二进制文件发布是最轻量、最可控的方式;但若需多环境、弹性伸缩或全球分发,必须走容器化 + 云平台流程,否则后续运维成本会指数级上升。
go build 生成可执行文件时必须关掉 CGO
本地 go build 出来的二进制在服务器上跑不起来,八成是没关 CGO_ENABLED。Linux 服务器通常没装 libc 或 musl 的 dev 包,动态链接会失败。
- 正确命令:
CGO_ENABLED=0 GOOS=linux go build -a -ldflags "-s -w" -o server . -
-s -w去掉调试符号和 DWARF 信息,能减小 30%+ 体积 - 别用
GOOS=windows或darwin编译后传到 Linux 跑——不是所有跨平台组合都默认支持 - 如果代码里用了
cgo(比如调 SQLite、OpenSSL),就得换纯 Go 实现,或改用 alpine 镜像配apk add ca-certificates
Docker 多阶段构建里 builder 阶段要先 copy go.mod 再 copy 源码
否则每次改一行代码,Docker 都会重下全部依赖,构建时间翻倍。这是缓存失效的最常见原因。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 顺序必须是:
COPY go.mod go.sum .→RUN go mod download→COPY . . - alpine 镜像里
go mod download可能因 DNS 或证书问题失败,加--insecure不安全,更稳妥的是在FROM golang:1.22-alpine后加RUN apk add --no-cache ca-certificates - 最终运行镜像别用
FROM scratch——它没/bin/sh,docker logs和exec -it全失效;alpine:latest是更实用的底线
Fly.io 部署时 PORT 环境变量不能硬编码在 main.go 里
Fly.io 强制通过 PORT 环境变量暴露端口,写死 :8080 会导致健康检查失败、实例反复重启。
立即学习“go语言免费学习笔记(深入)”;
- 读取方式必须是:
port := os.Getenv("PORT"), fallback 到"8080"仅用于本地开发 -
fly.toml中[services]下的internal_port必须和代码里监听的端口一致,否则流量进不来 - 第一次
flyctl deploy后,立刻跑flyctl status看Recent Events,出现failed health check就说明端口或路径不对 - 别在
fly.toml里设auto_start_machines = true同时又用services——两者冲突,部署会卡住
真正容易被忽略的是:所有云平台(Fly.io、微信云托管、AWS ECS)都要求应用启动后**立即响应 HTTP GET /healthz 或 /readyz**,哪怕只是返回 200。没加这个 endpoint,扩缩容和自动恢复就全失效。这不是可选项,是基础设施层的契约。

















