docker-compose.yml中service的build.context必须设为含go.mod的根目录,否则go build报错;容器间通信须用service名而非localhost;避免端口冲突需区分本地开发与集成测试场景;优化镜像体积应禁用cgo并剥离符号。

docker-compose.yml 里 service 的 build.context 必须指向含 Go 模块的根目录
Go 编译依赖 go.mod 所在路径作为模块根,若 build.context 设错(比如指向子目录或项目外),go build 会报 no Go files in 或 cannot find module。常见错误是把 context 写成 ./cmd/api,但 go.mod 其实在上层 ./。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 确认
go.mod所在路径就是你希望go build执行的当前工作目录 -
build.context填该路径(通常为.),再用build.dockerfile指定具体 Dockerfile 位置(如./cmd/api/Dockerfile) - 本地调试时,可先在宿主机运行
go list -m验证模块路径是否正确
Go 服务容器内无法访问其他 service(如 PostgreSQL、Redis)
Docker Compose 默认为每个 service 创建独立网络命名空间,容器间通信必须用 service 名作 host,而非 localhost 或 127.0.0.1。Go 程序若硬编码 localhost:5432,启动后连不上 PostgreSQL 容器。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 把数据库地址设为环境变量,例如
DB_HOST=postgres(service 名),并在 Go 代码中读取:os.Getenv("DB_HOST") - 确保
docker-compose.yml中 service 名与 Go 连接字符串中的 host 一致(大小写敏感,且不带端口) - 调试时进容器执行
nslookup postgres或ping postgres,验证 DNS 解析是否生效
本地热重载调试时,go run 和 docker-compose 启动方式混用导致端口冲突
很多人一边用 go run main.go 在宿主机跑服务,一边又 docker-compose up 启另一个实例,结果两个进程争抢 :8080,后者报错 Bind for 0.0.0.0:8080 failed: port is already allocated。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 明确区分场景:纯本地开发用
go run+docker-compose up db redis(只启依赖);集成测试才全量docker-compose up - 在
docker-compose.yml的 service 下加ports:显式暴露端口,但本地开发时可注释掉,避免干扰 - 用
go mod edit -replace或replace指令临时替换依赖路径,比反复 rebuild 容器更快
Go binary 构建体积大、启动慢,影响 compose 重启效率
默认 go build 生成的二进制包含调试符号、链接 libc,体积常超 20MB,Docker 层缓存易失效,每次 compose up --build 都要重新 copy 和启动。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- Dockerfile 中用
CGO_ENABLED=0 go build -a -ldflags '-s -w':禁用 cgo、剥离符号、压缩体积 - 优先使用
scratch或gcr.io/distroless/static作为基础镜像,避免打包整个 Alpine - 若需调试,单独维护一个
Dockerfile.debug,保留strace、curl等工具,不要在主构建流程里塞进去
最常被忽略的是:Go 服务的健康检查探针(healthcheck)没配超时和重试,导致 compose 等待过久才判定失败——这会让本地迭代节奏卡住,而不是立刻看到错误。










