You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一服务器运行两个Docker-Compose容器时数据库数据串流问题

问题根源与解决方案

你的问题核心是多个实例复用了同一数据库存储卷,同时容器名称/服务名称的全局唯一性冲突也加剧了这个问题,具体解决方法如下:

1. 数据库存储卷独立

当前db_test服务挂载了本地固定路径./data/postgres,启动第二个实例时,只要该路径不变,PostgreSQL会直接读取已有数据文件,导致两个实例共享同一份数据库。

修改方式:给每个实例分配独立的本地卷路径,或使用Docker命名卷并指定唯一名称:

# 第二个实例的db服务配置
db_test2:
  image: postgres
  container_name: db-test2
  restart: always
  environment:
    POSTGRES_USER: docker
    POSTGRES_PASSWORD: docker
    POSTGRES_DB: test2  # 可修改数据库名进一步隔离
  volumes:
    - ./data/postgres-test2:/var/lib/postgresql/data  # 独立存储路径

2. 容器与服务名称全局唯一

Docker容器名称是全局唯一的,若修改配置后未更新container_name字段,第二个实例要么启动失败,要么覆盖原有容器(导致你误以为启动新实例,但实际仍用旧数据)。同时,在同一外部traefik网络中,重复的服务名(如db_test)会导致DNS解析指向旧容器。

修改方式:

  • 要么删除container_name字段,让Docker自动生成唯一名称;
  • 要么给每个实例的容器名、服务名添加唯一后缀:
# 第二个实例的app服务配置
app:
  build: .
  container_name: test2  # 唯一容器名
  command: sh -c "uvicorn app.main:app --reload --host 0.0.0.0 --port 7779"  # 端口也要修改避免冲突
  restart: always
  volumes:
    - ./app/:/code/app
  labels:
    - "traefik.enable=true"
    - "traefik.subdomain=test2"  # 子域名唯一
    - "traefik.http.services.test2.loadbalancer.server.port=7779"  # traefik服务名唯一
    - "traefik.http.routers.test2.tls.certresolver=letsEncrypt"  # traefik路由名唯一
  env_file:
    - ./.env.test2  # 独立环境变量文件
  depends_on:
    - db_test2  # 对应新的db服务名

3. 环境变量隔离

确保第二个实例的.env文件中,数据库连接字符串指向新的DB服务/容器:

# .env.test2中的数据库配置
DATABASE_URL=postgres://docker:docker@db_test2:5432/test2

验证步骤

  1. 停止并移除旧实例的所有容器:docker-compose down
  2. 按上述修改配置,确保卷路径、容器名、服务名、端口、子域名全部唯一
  3. 启动新实例:docker-compose up -d
  4. 检查新数据库容器的卷挂载:docker inspect db-test2 | grep Mounts,确认路径正确

内容的提问来源于stack exchange,提问作者kirastel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 18:20:39