同一服务器运行两个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
验证步骤
- 停止并移除旧实例的所有容器:
docker-compose down - 按上述修改配置,确保卷路径、容器名、服务名、端口、子域名全部唯一
- 启动新实例:
docker-compose up -d - 检查新数据库容器的卷挂载:
docker inspect db-test2 | grep Mounts,确认路径正确
内容的提问来源于stack exchange,提问作者kirastel
相关产品推荐
相关产品推荐

