docker compose中service间通过内置dns以服务名通信,需共用自定义网络;go应用应使用wait-for-it.sh等待postgresql/redis就绪;开发时挂载源码+air热更新;敏感配置用.env文件(gitignore)管理。

docker-compose.yml 里 service 之间怎么互相访问
容器间通信靠的是 Docker 内置 DNS,同一网络下直接用服务名当 hostname。比如你定义了 redis 和 app 两个 service,app 里连 Redis 就写 redis:6379,不是 localhost:6379,也不是 127.0.0.1——后者在容器里指向自己,根本连不到 Redis 容器。
常见错误现象:connection refused 或超时,八成是用了 localhost;或者没显式声明 networks,导致默认网络隔离(尤其是用了多个 docker-compose.yml 文件时)。
- 确保所有 service 都在同一个自定义网络里,比如加
networks: [app-net],并在最外层定义networks: { app-net: {} } - Go 应用里数据库连接字符串写
postgres://user:pass@postgres:5432/dbname?sslmode=disable,不是localhost - 启动后进容器手动测试:
docker exec -it myapp sh -c "ping redis"或telnet redis 6379(需装 telnet)
Go 应用启动前怎么等 PostgreSQL 和 Redis 就绪
Docker Compose 默认不等依赖服务就启动,Go 程序一上来就 dial postgres:5432,大概率失败并 panic。别在 Go 里写死重试逻辑,用现成的健康检查工具更稳。
推荐用 wait-for-it.sh 或 dockerize ——它们本质都是轮询端口通不通,但比自己写 sleep+net.Dial 更可靠。
立即学习“go语言免费学习笔记(深入)”;
- 把
wait-for-it.sh下载进镜像(或挂载),然后在command里前置调用:command: ["sh", "-c", "./wait-for-it.sh postgres:5432 -- ./myapp"] - PostgreSQL 的
healthcheck不能只看端口,要执行 SQL,所以建议在 compose 文件里加:healthcheck: { test: ["CMD-SHELL", "pg_isready -U user -d dbname"], interval: 30s } - Redis 不需要复杂健康检查,
test: ["CMD", "redis-cli", "ping"]足够,但注意它默认返回PONG,得配合|| exit 1判断失败
Go 编译产物怎么热更新,避免每次改代码都 rebuild 镜像
本地开发阶段,别把 Go 源码编译进镜像再跑,那样改一行就要 docker-compose build,太慢。应该让容器里运行的是未编译的源码,用 air 或 fresh 监听文件变化自动 rebuild + restart。
关键点:挂载本地代码目录到容器内,并确保 Go mod cache、vendor 等路径也映射或预置好,否则 go run 会卡在下载依赖。
- 在
volumes里挂载:./src:/app,同时设working_dir: /app - 用多阶段构建镜像时,dev 阶段保留
go环境和air工具,而不是最终只放二进制的 stage - Go mod cache 建议挂载宿主机目录:
~/.cache/go-build:/root/.cache/go-build,加速重复编译 - 如果用
air,配置.air.toml忽略node_modules、vendor等大目录,不然 inotify 监听容易爆限
环境变量怎么安全传给 Go 应用,又不硬编码进 compose 文件
数据库密码、Redis 地址这些敏感或易变配置,绝不能写死在 docker-compose.yml 里。Docker Compose 支持 .env 文件和 env_file,但要注意加载顺序和覆盖规则。
Go 应用读取环境变量时,优先级要清晰:本地 .env → compose 的 environment → env_file → 宿主机环境。混乱就会导致本地跑通、CI 失败。
- 在项目根目录放
.env(gitignore 掉),内容如:DB_HOST=postgres、REDIS_ADDR=redis:6379 - compose 文件中用
environment: { DB_HOST: ${DB_HOST} },不要写DB_HOST: postgres - 若要用
env_file(比如不同环境不同配置),记得它只影响容器内环境变量,Go 里仍要通过os.Getenv读,且它不会覆盖已存在的environment值 - 密码类字段,宁可用
docker secret,但本地开发没必要,.env+gitignore足够
最容易被忽略的是:PostgreSQL 容器首次启动时会初始化数据库,但如果你反复 docker-compose down -v,数据卷清空,下次启动又得等 init script 重跑;而 Redis 默认不持久化,redis.conf 里得显式开 appendonly yes 才能保留键值——这些细节不碰上一次就不会记住。










