PostgreSQL容器连不上主因是端口未映射和就绪检查不当:需显式配置ExposedPorts、用ForListeningPort而非日志等待、连接串加sslmode=disable、动态获取MappedPort、仅用Terminate()清理容器。

PostgreSQL容器连不上?90%是端口和就绪检查没配对
直接 sqlx.Open("postgres://...", ...) 报 dial tcp 127.0.0.1:5432: connect: connection refused,不是 Docker 没装,而是容器还没真正 ready 就去连了。
-
ExposedPorts必须显式写[]string{"5432/tcp"},否则 Docker 不做端口映射,localhost:5432根本不通 -
WaitingFor别用ForLog("database system is ready")—— PostgreSQL 启动日志有缓冲、可能被截断;改用wait.ForListeningPort("5432/tcp")更稳 - 连接字符串里必须加
sslmode=disable,testcontainers 启的 PG 默认不带证书,不关 SSL 就会卡在 TLS 握手 - 别硬写
localhost:5432,要用container.MappedPort(ctx, "5432")动态取宿主机实际端口,尤其在 CI 或多测试并行时
测试跑完容器还在?Terminate 顺序错了
下次测试报 port already in use 或 CI 磁盘爆满,大概率是容器没真正退出,不是忘了 defer container.Terminate(),而是误调了 Stop()。
-
container.Stop()是异步发 SIGTERM 后立刻返回,不等进程结束;Terminate()才会等 shutdown 完成(默认最多等 10 秒),并清理关联的匿名 volume - 永远只用
defer container.Terminate(),不要自己调Stop()—— 如果先Stop()再Terminate(),后者发现容器已停,什么也不做 - 多个容器时,在
TestMain里统一管理生命周期:启动放func TestMain开头,os.Exit(m.Run())前批量Terminate()
初始化 SQL 不执行?数据目录没清干净
你写了 Files 把 init.sql 塞进容器,但 psql -c '\dt' 查不到表 —— PostgreSQL 只在空数据目录首次启动时执行 /docker-entrypoint-initdb.d/ 下的脚本。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 每次测试必须确保容器和它挂载的匿名 volume 一起销毁,靠
Terminate()就够,不用额外docker volume rm - 别挂载宿主机文件(如
Mounts: []testcontainers.ContainerMount{...}),改用ContainerRequest.Files直接写内容进容器路径,避免权限或路径问题 - 验证是否生效:容器启动后
docker exec -it <id> ls -l /docker-entrypoint-initdb.d/</id>,再查psql -U testuser -c 'SELECT * FROM pg_tables;'
Redis SET 了 GET 不到?不是网络问题,是 client 缓存行为
Go 测试里 client.Set(...).Err() 成功,但紧跟着 client.Get(...).Val() 返回空字符串 —— 很可能不是 Redis 没收到,而是 client pipeline 或连接复用导致时序错乱。
- 默认
redis.NewClient启用 pipeline,SET 和 GET 可能被合并或延迟发送;加DisableIndentity: true关掉(注意拼写是DisableIndentity,非Identity) - 写操作后别只 check error,要显式等完成:
client.Set(ctx, "k", "v", 0).Err(),读前可加client.Wait(ctx, 1, 100*time.Millisecond)等主从同步(如果启了 replica) - 调试时临时加
time.Sleep(10 * time.Millisecond)能快速确认是否纯时序问题,但上线必须换真实等待逻辑
最常被忽略的其实是网络绑定:PostgreSQL 默认只监听 127.0.0.1,Redis 默认 bind 127.0.0.1 —— 容器内 localhost ≠ 宿主机 localhost。必须通过 Env 或 Cmd 显式设 listen_addresses='*'、--bind 0.0.0.0:6379,否则暴露端口也没用。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










