Web与数据库容器协同的核心是网络可达、连接就绪和配置一致:服务名即DNS名,需用db而非localhost;依赖需配合healthcheck与重试机制;配置通过环境变量分离;数据持久化必须使用命名卷。
web 与数据库容器的协同,核心在于让 web 服务能稳定、可靠地连接并使用数据库,而不是简单“启动就完事”。关键不在启动顺序,而在网络可达性、连接就绪性和配置一致性。
服务命名即 DNS 名,用服务名代替 localhost
Compose 自动为项目创建默认桥接网络,所有 service 都加入该网络,并以服务名为 DNS 主机名。后端代码里连接数据库必须写 db:5432(假设服务名为 db),不能写 localhost:5432 或 127.0.0.1:5432——后者在容器内指向自己,必然失败。
- 前端(如 Nginx)若需代理到后端,upstream 地址也用
backend:3000,而非localhost - 数据库服务名一旦定义为
database,后端环境变量DB_HOST就应设为database
依赖 ≠ 就绪:用 healthcheck + depends_on condition 控制真实可用性
depends_on 只控制容器启动顺序,不等待数据库进程真正监听连接。PostgreSQL 容器可能已启动,但初始化还没完成,此时后端连接会直接报错。
- 给数据库服务加上
healthcheck,例如 PostgreSQL 可用pg_isready -U admin - 后端服务中
depends_on改用条件形式:condition: service_healthy - 即使如此,仍建议后端代码内置连接重试逻辑(如指数退避),避免启动瞬间失败崩溃
环境变量注入 + 外部配置分离,适配多环境
数据库地址、密码、库名等不应硬编码在 YAML 或应用代码里,而应通过环境变量传递,并从 .env 文件或宿主机读取。
- 在
docker-compose.yml中用${DB_PASSWORD}引用变量,配合.env文件管理敏感值 - 数据库初始化 SQL 放在
./db/init.sql,通过 volume 挂载到/docker-entrypoint-initdb.d/ - 前端构建产物(如
dist/)挂载进 Nginx 容器,避免每次 rebuild 镜像
数据持久化靠命名卷,不是 bind mount
数据库数据必须持久保存,否则容器重启后整个库清空。使用命名卷(named volume)而非相对路径 bind mount。
- 定义
volumes: pgdata:(顶层),再在db服务中挂载- pgdata:/var/lib/postgresql/data - 命名卷由 Docker 管理,自动跨容器生命周期保留,且与宿主机路径解耦
- 不要写成
- ./pgdata:/var/lib/postgresql/data,容易因权限、路径不存在或 Git 忽略导致问题











