Go服务用Echo框架无法在docker-compose.yml中运行,主因是构建路径错误(build.context未指向含go.mod的目录)、监听地址错误(需0.0.0.0:8080而非127.0.0.1)、依赖服务未真正就绪(depends_on不保证DB初始化完成)。

Go 服务用 Echo 框架写完,直接扔进 docker-compose.yml 就跑不起来?八成不是 Echo 的问题,而是构建路径、端口监听、依赖就绪这三关没过。
docker-compose.yml 中的 build.context 必须包含 go.mod
如果你的 Echo 服务在 ./svc/auth 下,而 go.mod 也在该目录里,那 build.context 就得写成 ./svc/auth,不能写成 . 或 ./svc。Docker 构建时以 context 为工作目录,go build 需要读取 go.mod 才能解析模块路径。
-
build: .+dockerfile: ./svc/auth/Dockerfile是错的 —— Docker 不会自动跳到上层找go.mod - 构建阶段执行
go mod download,别在宿主机提前拉 —— 否则跨 Go 版本或平台时go.sum校验失败 - 多服务项目中,每个服务的
go.mod应独立,避免replace指向本地路径(如replace github.com/xxx/auth => ./svc/auth),否则容器内路径不存在
Echo 服务必须监听 0.0.0.0:8080,不能是 127.0.0.1:8080
Docker 容器内 127.0.0.1 指的是自己,不是宿主机。如果 Echo 启动时写的是 e.Start("127.0.0.1:8080"),那容器内健康检查、其他服务调用都会连不上。
- 正确写法:
e.Start(":8080")或e.Start("0.0.0.0:8080") -
EXPOSE 8080只是声明,不起作用;真正生效的是ports: ["8080:8080"]和程序绑定地址 - 健康检查建议用 HTTP 探针:
HEALTHCHECK --interval=10s CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1(Alpine 镜像默认有wget)
depends_on 不等于数据库就绪,Echo 连 PostgreSQL 必须重试
depends_on 只保证 PostgreSQL 容器进程已启动,不代表它已经初始化完用户、建好库、端口可连。Echo 一上来就 sql.Open,大概率报 dial tcp 172.20.0.3:5432: connect: connection refused。
立即学习“go语言免费学习笔记(深入)”;
- PostgreSQL service 要加
healthcheck:pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB} - Echo service 的
depends_on改成:condition: service_healthy - 代码里仍需重试逻辑,比如用
github.com/jackc/pgx/v5/pgxpool的MaxRetries,或手动轮询直到pool.Ping()成功
本地开发别把 Echo 服务塞进 docker-compose.yml
把 Echo 服务也写进 docker-compose.yml 并用 go run 启动,会导致调试中断、断点失效、go.sum 缓存无法复用、每次改代码都重建镜像 —— 开发体验极差。
- 推荐做法:Docker Compose 只管中间件(PostgreSQL、Redis、Consul),Echo 服务用宿主机进程运行 +
air热重载 - 安装
air:go install github.com/cosmtrek/air@latest -
.air.toml关键配置:root = "."、bin = "./tmp/main"、include_dirs = ["."],并排除node_modules和vendor - 连接中间件时地址统一用
127.0.0.1(不是localhost),因为宿主机 Go 进程要直连 Docker 桥接网络里的服务
最常被忽略的一点:Echo 服务启动后,要等所有依赖(DB、Cache、Config Server)真正 ready 才开始注册路由或接受请求 —— 这个“真正 ready”不是靠 depends_on,而是靠代码里的显式探测和重试。


















