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

Flask应用连接MongoDB失败求助(Docker-Compose环境)

Flask连接MongoDB时DNS解析错误的解决方法

问题详情

执行Flask应用的GET/POST请求时遇到以下错误:

mongo:27017: [Errno -2] Name does not resolve (configured timeouts:
socketTimeoutMS: 20000.0ms, connectTimeoutMS: 20000.0ms), Timeout:
30s, Topology Description: <TopologyDescription id:
657c619ae1e4696f65e708c2, topology_type: Unknown, servers:
[<ServerDescription ('mongo', 27017) server_type: Unknown, rtt: None,
error=AutoReconnect('mongo:27017: [Errno -2] Name does not resolve
(configured timeouts: socketTimeoutMS: 20000.0ms, connectTimeoutMS:
20000.0ms)')>]>

相关代码

app.py

from flask import Flask, jsonify
from pymongo import MongoClient
from loguru import logger
from bson.json_util import dumps

app = Flask(__name__)

MONGO_URI = "mongodb://admin:admin@mongo:27017/"

@app.route('/', methods=['GET'])
def get_data():
    try:
        logger.info('Connecting to MongoDB')
        client = MongoClient(MONGO_URI)
        logger.info('Connected to MongoDB')
        db = client.test
        collection = db.test
        data = collection.find({})
        serialized_data = dumps(data)
        logger.info('Data retrieved successfully')
        return jsonify({"data": serialized_data}), 200
    except Exception as e:
        return jsonify({"error": f"{str(e)}"}), 500

@app.route('/', methods=['POST'])
def create_data():
    try:
        logger.info('Connecting to MongoDB')
        client = MongoClient(MONGO_URI)
        logger.info('Connected to MongoDB')
        db = client.test
        collection = db.test
        data = collection.insert_one({"name": "test"})
        logger.info('Data created successfully')
        return jsonify({"data": data}), 200
    except Exception as e:
        return jsonify({"error": f"{str(e)}"}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0')

docker-compose.yml

version: '3.9'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    depends_on:
      - mongodb
      - nginx

  nginx:
    image: nginx:latest
    ports:
      - "80:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro

  mongodb:
    image: mongo:latest
    ports:
      - "27017:27017"
    environment:
      - MONGO_INITDB_DATABASE=test
      - MONGO_INITDB_ROOT_USERNAME=admin
      - MONGO_INITDB_ROOT_PASSWORD=admin
      - MONGO_URI=mongodb://admin:admin@mongodb:27017/test
    volumes:
      - mongodb_data:/data/db

volumes:
  mongodb_data:

用户疑问:日志显示请求已执行到连接代码行,但仍出现连接错误,该如何解决?


解决步骤

1. 修正MongoDB主机名

Docker容器间通信依赖服务名作为主机名,docker-compose中MongoDB服务的名称是mongodb,但app.py里的MONGO_URI用的是mongo,两者不匹配导致DNS解析失败。修改app.py中的MONGO_URI:

MONGO_URI = "mongodb://admin:admin@mongodb:27017/"

2. 修复连接日志的误导性

PyMongo的MongoClient初始化时不会立即建立连接,只有执行数据库操作(如find()、insert_one())时才会真正尝试连接,所以你看到的logger.info('Connected to MongoDB')并不代表连接成功。可以添加连接验证步骤,提前捕获错误:

client = MongoClient(MONGO_URI)
# 主动验证连接
client.admin.command('ping')
logger.info('Connected to MongoDB')

3. 确保MongoDB服务就绪后启动web服务

depends_on仅保证容器启动顺序,不保证MongoDB服务完全就绪。可以给mongodb服务添加健康检查,确保服务可用后再启动web服务:
在docker-compose的mongodb服务中添加:

healthcheck:
  test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
  interval: 5s
  timeout: 5s
  retries: 5

同时修改web服务的depends_on配置:

depends_on:
  mongodb:
    condition: service_healthy
  nginx:
    condition: service_started

4. 统一环境变量(可选优化)

将MONGO_URI放到docker-compose的web服务环境变量中,避免代码硬编码:
在web服务下添加:

environment:
  - MONGO_URI=mongodb://admin:admin@mongodb:27017/

然后app.py中读取环境变量:

import os
MONGO_URI = os.getenv("MONGO_URI", "mongodb://admin:admin@mongodb:27017/")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:23:36