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

Docker Compose部署Flask与MongoDB时容器内连接失败问题求助

问题根因
  • 容器间通信端口配置错误:docker-compose.yaml中ports字段的格式是宿主机映射端口:容器内部监听端口,你配置的"27018:27017"仅对宿主机生效——也就是你本地的MongoDB Compass、PyCharm数据库工具需要通过localhost:27018连接Mongo实例;但同属一个Compose网络的Flask容器和Mongo容器通信时,必须直接访问Mongo容器内部的默认监听端口27017,你之前URI写27018会直接触发端口无服务监听的连接拒绝错误。
  • 启动时序不匹配:Compose的depends_on配置仅保证Mongo容器先于Flask容器启动,不会等待Mongo完成初始化、加载完数据、可以接收连接请求,Flask如果在Mongo就绪前发起连接也会失败。
  • Flask端口映射不匹配:你的main.py中Flask启动监听的是8100端口,但Compose里backend服务的端口映射写的是'8100:5000',就算数据库连接正常,宿主机也无法通过8100端口访问Flask服务。
修复步骤

1. 修正MongoDB连接URI

把main.py中所有Mongo连接URI的端口从27018改为27017,主机名保留Compose服务名db_mongo,不要用localhost(localhost指向Flask容器自身,容器内没有运行Mongo服务),正确URI如下:

uri = 'mongodb://flask_api_user:dbPass@db_mongo:27017/?authMechanism=DEFAULT&authSource=flask_api_db'

不管是直接用pymongo.MongoClient初始化,还是传给flask_pymongo的uri参数,都使用这个地址。

2. 补全Mongo初始化环境变量

检查./env/.env_database文件,确保配置了Mongo初始root账号,否则init-mongo.js中的认证逻辑会执行失败,业务账号无法创建:

MONGO_INITDB_ROOT_USERNAME=mk
MONGO_INITDB_ROOT_PASSWORD=adminPass

3. 添加连接重试逻辑,解决启动时序问题

不要在模块加载阶段直接发起数据库连接,改成带重试的初始化逻辑,等Mongo完全就绪再建立连接:

import time
import pymongo
from flask import Flask, jsonify
from pymongo.errors import ServerSelectionTimeoutError, ConnectionFailure

app = Flask(__name__)
client = None
db = None

# 启动时循环重试连接Mongo
while True:
    try:
        client = pymongo.MongoClient(
            'mongodb://flask_api_user:dbPass@db_mongo:27017/?authMechanism=DEFAULT&authSource=flask_api_db',
            serverSelectionTimeoutMS=5000
        )
        # 验证连接可用性
        client.admin.command('ismaster')
        db = client['flask_api_db']
        print("MongoDB连接成功", flush=True)
        break
    except (ServerSelectionTimeoutError, ConnectionFailure) as e:
        print(f"MongoDB未就绪,2秒后重试: {str(e)}", flush=True)
        time.sleep(2)


@app.route('/')
def index():
    return 'Test2'


@app.route("/add_one/")
def add_one():
    db.my_collection.insert_one({'title': "todo title", 'body': "todo body"})
    return jsonify(message="success")


if __name__ == '__main__':
    # 二选一:要么把端口改成5000匹配现有Compose端口映射,要么改Compose映射为8100:8100
    app.run(debug=True, host='0.0.0.0', port=5000)

4. 重启服务验证

因为修改了初始化相关配置,需要先清理旧的无效数据卷,再重新构建启动服务:

docker compose down -v
docker compose up --build

看到日志输出MongoDB连接成功后,即可通过宿主机8100端口访问Flask服务,数据库读写操作可正常执行。

注意:init-mongo.js脚本仅在Mongo数据卷首次初始化(数据目录为空)时执行,如果后续修改初始化脚本,都需要先执行docker compose down -v清空旧数据卷再启动,否则脚本不会重新运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 00:01:04