flask_pymongo结合docker-compose初始化MongoDB及KeyError问题解决
报错根因
出现KeyError: 'MONGODB_USERNAME'的核心原因:
- 你当前是直接在本地Windows环境执行
python app.py,本地系统环境变量中根本不存在MONGODB_USERNAME这类原本设计给docker容器传入的配置。Python中os.environ[键名]的读取方式在键不存在时会直接抛出KeyError中断程序,没有任何容错空间。 - 就算后续把应用打包到容器内运行,硬取环境变量的写法也完全不健壮,只要docker-compose配置漏写任意一个环境变量,程序就会直接崩溃。
修正Flask-PyMongo初始化逻辑
要实现既支持本地调试快速运行,又能对接docker-compose的环境变量配置,需要替换原有配置写法:
- 用带兜底默认值的
os.getenv替代直接抛错的os.environ[键]读取方式 - 补全Mongo连接URI的认证参数,适配官方Mongo镜像的认证逻辑
- 替换
app.py中硬拼MONGO_URI的代码段,修改后的核心逻辑如下:from flask import Flask, jsonify from flask_pymongo import PyMongo import os import json_logging, logging, sys app = Flask(__name__) json_logging.init_flask(enable_json=True) json_logging.init_request_instrument(app) logger = logging.getLogger("mongodb-service") logger.setLevel(logging.DEBUG) logger.addHandler(logging.StreamHandler(sys.stdout)) # 读取环境变量,配置本地调试兜底值,避免KeyError MONGO_USER = os.getenv("MONGODB_USERNAME", "root") MONGO_PASS = os.getenv("MONGODB_PASSWORD", "pass") MONGO_HOST = os.getenv("MONGODB_HOSTNAME", "localhost") MONGO_DB = os.getenv("MONGODB_DATABASE", "cars_db") # 连接URI必须加authSource=admin参数,否则会因为认证源不匹配被Mongo拒绝连接 app.config["MONGO_URI"] = f"mongodb://{MONGO_USER}:{MONGO_PASS}@{MONGO_HOST}:27017/{MONGO_DB}?authSource=admin" mongo = PyMongo(app) db = mongo.db @app.route('/') def ping_server(): return "Welcome to best website ever" @app.route('/cars') def get_stored_cars(): _cars = db.car_tb.find() cars = [{"brand": car["brand"], "model": car["model"]} for car in _cars] return jsonify({"cars": cars}) - 修正docker-compose配置的缺失问题:
- 你当前贴出的compose文件只声明了app服务,缺少mongodb服务的定义块,需要新增mongodb服务配置,开启认证逻辑,和应用传入的用户名、密码完全匹配。
- 确保mongodb的服务名和应用配置里的
MONGODB_HOSTNAME的值一致——你目前写的MONGODB_HOSTNAME: mongodb-flask,就需要把mongodb服务的服务名设置为mongodb-flask,不然同网络下的容器无法解析到Mongo服务的地址。 - 保证app和mongodb服务挂载在同一个
app_network网络下,否则容器之间无法通过服务名通信。
额外踩坑提醒
- 你当前用的
depends_on配置只会等待mongodb容器启动完成,不会等待Mongo服务内部完全就绪、可以接受连接,应用启动时如果Mongo还在初始化,会出现连接超时的报错。可以在mongodb服务块中配置healthcheck,判断Mongo正常启动后再启动app服务,避免启动顺序导致的连接问题。 - 本地调试时不需要手动配置系统环境变量,
os.getenv配置的兜底值会直接使用本地localhost地址连接你本机部署的Mongo实例,不会再触发KeyError报错。
内容的提问来源于stack exchange,提问作者Jesus Fernandez
相关产品推荐
相关产品推荐

