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
相关产品推荐
相关产品推荐

