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

Docker部署Flask应用无法持久化数据到MongoDB:日志无错但库无数据

问题

我正在开发一个运行在Docker容器中的Flask应用,该应用连接到另一个独立容器中的MongoDB。所有服务启动无报错,日志显示MongoDB连接成功,但执行用户注册等操作后,MongoDB数据库中并未出现新数据。容器运行和通信正常,且已确保MongoDB用户拥有必要权限,相关配置文件与环境信息如下:

环境

  • Python: 3.9
  • MongoDB: 4.0.8
  • Docker: 使用Docker Compose部署

Dockerfile

FROM python:3.9-slim

WORKDIR /app

RUN apt-get update && apt-get install -y \
    build-essential \
    python3-dev \
    && rm -rf /var/lib/apt/lists/*

COPY req.txt .
RUN pip install --no-cache-dir -r req.txt
RUN pip install gunicorn

COPY . .

RUN mkdir -p logs

RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser

EXPOSE 5001

CMD ["gunicorn", "--bind", "0.0.0.0:5001", "--workers", "4", "--timeout", "120", "app:app"]

docker-compose.yml

version: '3'

services:
  flask:
    build:
      context: .
      dockerfile: Dockerfile
    image: <my-flask-image>:latest
    deploy:
      replicas: 3
    ports:
      - "6001-6003:5001"
    environment:
      MONGO_URI: mongodb://<my-username>:<my-password>@mongodb:27017/<my-db>?authSource=admin
      APP_ENV: "prod"
      APP_DEBUG: "False"
      APP_PORT: 5001
    volumes:
      - ./logs:/app/logs
    depends_on:
      - mongodb
    networks:
      - backend
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  mongodb:
    image: mongo:4.0.8
    container_name: mongodb
    restart: unless-stopped
    ports:
      - "27017:27017"
    command: mongod --auth
    environment:
      MONGO_INITDB_ROOT_USERNAME: <my-username>
      MONGO_INITDB_ROOT_PASSWORD: <my-password>
      MONGO_INITDB_DATABASE: admin 
    volumes:
      - mongodbdata:/data/db
      - ./init.js:/docker-entrypoint-initdb.d/init-mongo.js
    networks:
      - backend

networks:
  backend:
    driver: bridge

volumes:
  mongodbdata:
    driver: local

MongoDB初始化脚本(init-mongo.js)

db = db.getSiblingDB('admin');

db.createUser({
  user: '<my-username>',
  pwd: '<my-password>',
  roles: [
    { role: 'userAdminAnyDatabase', db: 'admin' },
    { role: 'readWriteAnyDatabase', db: 'admin' },
    { role: 'dbAdminAnyDatabase', db: 'admin' },
    { role: 'clusterAdmin', db: 'admin' }
  ]
});

db = db.getSiblingDB('<my-db>');
db.createUser({
  user: '<my-username>',
  pwd: '<my-password>',
  roles: [
    { role: 'readWrite', db: '<my-db>' },
    { role: 'dbAdmin', db: '<my-db>' }
  ]
});

config/settings.py

import os
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# MongoDB Configuration
MONGO_URI = os.getenv('MONGO_URI', 'mongodb://<my-username>:<my-password>@mongodb:27017/<my-db>?authSource=admin')
DB_NAME = '<my-db>'

config/db.py

from pymongo import MongoClient
import logging

class Database:
    client = None
    db = None

    @classmethod
    def initialize(cls):
        """Initialize database connection with retries"""
        cls.client = MongoClient(
            MONGO_URI,
            maxPoolSize=50,
            waitQueueTimeoutMS=2500,
            connectTimeoutMS=2500,
            serverSelectionTimeoutMS=5000
        )
        cls.db = cls.client[DB_NAME]
        cls._create_indexes()
        logging.info("MongoDB connection successful")

    @classmethod
    def _create_indexes(cls):
        """Create necessary indexes"""
        cls.db.tenants.create_index("tenant_name", unique=True)
        cls.db.tenant_configs.create_index("cypherDomain", unique=True)
        logging.info("MongoDB indexes created successfully")

    @classmethod
    def get_db(cls):
        """Get database instance with connection check"""
        if cls.db is None:
            cls.initialize()
        return cls.db

db_instance = Database()

应用日志

2024-11-13 20:24:07 INFO:root:Application starting up
2024-11-13 20:24:07 INFO:root:MongoDB URI: <my-url>
2024-11-13 20:24:07 INFO:root:Log file location: logs/backend_20241113.log
2024-11-13 20:24:07 INFO:root:Application starting up
2024-11-13 20:24:07 INFO:root:MongoDB URI: <my-url>
2024-11-13 20:24:07 INFO:root:MongoDB connection successful
2024-11-13 20:24:07 INFO:root:Log file location: logs/backend_20241113.log
2024-11-13 20:24:07 INFO:root:MongoDB indexes created successfully
2024-11-13 20:24:07 INFO:root:MongoDB connection successful
2024-11-13 20:24:07 INFO:root:Application starting up
2024-11-13 20:24:07 INFO:root:MongoDB URI: <my-url>
2024-11-13 20:24:07 INFO:root:Log file location: logs/backend_20241113.log
2024-11-13 20:24:07 INFO:root:MongoDB indexes created successfully
2024-11-13 20:24:08 INFO:root:MongoDB connection successful
2024-11-13 20:24:08 INFO:root:MongoDB indexes created successfully
2024-11-13 20:24:08 INFO:root:Application starting up
2024-11-13 20:24:08 INFO:root:MongoDB URI: <my-url>
2024-11-13 20:24:08 INFO:root:Log file location: logs/backend_20241113.log
2024-11-13 20:24:08 INFO:root:MongoDB connection successful
2024-11-13 20:24:08 INFO:root:MongoDB indexes created successfully
2024-11-13 20:25:32 INFO:root:Signup data: {'email': 'db2@gmail.com', 'password': 'test123', 'tenant_name': 'db2', 'authProvider': 'email'}

请问哪些原因会导致数据无法插入到MongoDB中?


可能的原因及排查方案
  • 注册请求的数据库写入逻辑未执行:日志仅打印了Signup数据,但无数据库写入操作的日志。检查注册接口代码,确认是否调用了insert_one/insert_many等写入方法,是否存在参数校验不通过、分支逻辑跳过写入的情况。
  • 数据库写入异常未捕获记录:如果插入过程中出现错误(比如唯一键冲突、字段约束不满足),但代码未添加try-except捕获并打印日志,会导致数据未写入但无报错提示。在数据库写入代码块添加异常捕获,输出详细错误信息。
  • 连接的数据库/集合不匹配:确认DB_NAME配置是否正确,注册数据是否写入了tenants集合(索引创建在该集合)。进入MongoDB容器执行mongo -u <my-username> -p <my-password> --authenticationDatabase admin <my-db>,再用db.tenants.find()查询数据,验证是否写入到了目标集合。
  • 事务未提交:如果代码中使用了MongoDB事务但未执行commit操作,数据不会持久化到数据库。检查是否存在开启事务后遗漏提交的逻辑。
  • Gunicorn多进程连接问题:虽然Database类是单例,但Gunicorn多进程模式下每个worker会初始化独立的数据库连接。可以在写入时打印当前进程ID和数据库实例标识,确认连接是否正常工作。
  • MongoDB容器自身问题:查看MongoDB容器日志(docker logs mongodb),检查是否有磁盘空间不足、锁等待、写入权限等警告或错误。
  • 环境变量加载冲突:load_dotenv()会优先加载本地.env文件,如果该文件中的MONGO_URI指向本地MongoDB而非容器内的实例,会导致数据写入到本地数据库而非目标容器。检查.env文件是否存在、内容是否正确。
  • 索引创建异常:日志显示索引创建成功,但可手动验证:进入MongoDB执行db.tenants.getIndexes(),确认tenant_name的唯一索引是否存在且正常。若索引创建失败,写入时可能因约束冲突失败但未被捕获。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:02:05