环境变量未生效主因是加载路径错误或未显式指定:docker compose默认不读.env.dev,须用--env-file .env.dev启动;.env仅替换yml占位符,容器内变量需通过environment或env_file声明,并用docker compose config验证是否展开。
开发环境隔离不是“配好就能跑”,而是持续验证和主动防御的过程。真正卡住团队的,往往不是配置写不出来,而是改了配置没生效、服务连不上、日志看不出错、本地调试却连上测试库——这些问题背后,90%都源于隔离机制被无意绕过或配置未正确加载。
环境变量没生效?检查加载路径和优先级
Docker Compose 加载环境变量有明确顺序:命令行参数 > --env-file 指定文件 > 项目根目录下的 .env 文件 > 系统环境变量。开发中常误以为改了 .env.dev 就自动生效,但默认情况下 Compose 并不读它。
- 必须显式使用
--env-file .env.dev启动,例如:docker compose --env-file .env.dev up -d - 若用
COMPOSE_PROJECT_NAME=dev-app docker compose up,仅改变项目命名空间,不加载变量 -
.env文件只用于替换docker-compose.yml中的${VAR}占位符,不注入容器内部 —— 容器内环境变量需靠environment:或env_file:显式声明 - 验证是否加载成功:运行
docker compose config,查看输出中environment字段是否已展开为真实值
服务间能 ping 通但连不上端口?查网络归属与暴露策略
同一 Compose 项目中,服务默认在同一个自定义网络里,可通过服务名访问(如 curl http://db:5432),但这不等于端口就一定可连。常见断点:
在 Linux 上通过 Docker 运行 OpenClaw,并使用 Tailscale 实现远程访问。⚠️ 涉及 sudo、Docker、Tailscale和凭证挂载——请先查阅安全章节...
- 数据库服务(如 PostgreSQL)默认只监听
localhost,需在配置中设listen_addresses = '*'并开放pg_hba.conf权限 - Redis 默认绑定
127.0.0.1,开发环境应加bind 0.0.0.0和protected-mode no - 确认容器实际所处网络:
docker inspect <container_name> | grep NetworkMode</container_name>,避免因network_mode: host导致 DNS 解析失效 - 不要依赖
depends_on判断服务就绪 —— 它只控制启动顺序,不校验端口是否监听成功;建议配合健康检查(healthcheck)或启动脚本重试
多个项目同时运行却互相干扰?强制命名空间隔离
默认情况下,Docker Compose 使用当前目录名作为项目前缀,生成网络、卷、容器名。如果两个项目都叫 myapp,它们的 myapp_default 网络会冲突,导致服务意外互通。
- 每次启动时指定唯一项目名:
docker compose --project-name dev-team-a up -d - 或统一通过环境变量设置:
export COMPOSE_PROJECT_NAME=dev-$(whoami)-$(basename $PWD) - 删除残留资源前先确认范围:
docker compose down只删当前项目,而docker network prune会清空所有未使用的网络 —— 生产环境慎用 - 推荐在
docker-compose.yml顶层显式声明name:字段(v2.23+ 支持),替代隐式推导
配置改了但容器没更新?理解重建与重启的区别
docker compose up 默认复用已有容器,即使 docker-compose.yml 或环境变量已变,也不会重新创建容器 —— 这是隔离失效的高发场景。
- 强制重建并拉取最新镜像:
docker compose up --force-recreate --build --pull - 只重建某服务:
docker compose up --force-recreate --no-deps web - 彻底清理再启(含卷):
docker compose down -v && docker compose up -d—— 注意-v会删除命名卷,慎用于数据库数据卷 - 验证容器是否真用了新配置:进入容器执行
env | grep ENV_NAME或cat /app/config.yaml,别只信日志输出










