本文介绍了Django + Mongo + Docker获取pymongo.errors.ServerSelectionTimeoutError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力使用Django,Djongo,Mongo和Docker Compose来运行一个简单的应用程序.我的设置如下:

I've been struggling to get a simple app running using Django, Djongo, Mongo, and Docker Compose. My setup looks like this:

docker-compose.yml

docker-compose.yml

services:
  mongodb:
    image: mongo:latest
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: mongoadmin
      MONGO_INITDB_DATABASE: django_mongodb_docker
    ports:
      - 27017:27017

  web:
    build: ./src
    restart: always
    command: python src/manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - 8000:8000
    links:
      - mongodb

Dockerfile

Dockerfile

FROM python:3
ENV PYTHONUNBUFFERED=1
RUN mkdir /code
COPY . /code/
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt

settings.py

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'djongo',
        'HOST': 'mongodb',
        'PORT': 27017,
        'USER': 'root',
        'PASSWORD': 'mongoadmin',
        'AUTH_SOURCE': 'admin',
        'AUTH_MECHANISM': 'SCRAM-SHA-1',
    }
}

令人讨厌的是,我能够从Web容器中使用pymongo连接到运行mongo的容器.如下.

What is annoying is that I am able to use pymongo from my web container to connect to the container running mongo. That works as follows.

from pymongo import MongoClient

c = MongoClient(
    'mongodb://mongodb:27017',
    username='root',
    password='mongoadmin',
    authSource='admin',
    authMechanism='SCRAM-SHA-1')

print(c.server_info())

问题是,当我从Web容器中运行迁移时,出现以下错误.

The issue is that when I go to run migrations from within my web container I get the following error.

Traceback (most recent call last):
  File "/code/src/manage.py", line 22, in <module>
    main()
  File "/code/src/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.9/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.9/site-packages/django/core/management/__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python3.9/site-packages/django/core/management/base.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/lib/python3.9/site-packages/django/core/management/base.py", line 371, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python3.9/site-packages/django/core/management/base.py", line 85, in wrapped
    res = handle_func(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/core/management/commands/migrate.py", line 92, in handle
    executor = MigrationExecutor(connection, self.migration_progress_callback)
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/executor.py", line 18, in __init__
    self.loader = MigrationLoader(self.connection)
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/loader.py", line 53, in __init__
    self.build_graph()
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/loader.py", line 216, in build_graph
    self.applied_migrations = recorder.applied_migrations()
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/recorder.py", line 77, in applied_migrations
    if self.has_table():
  File "/usr/local/lib/python3.9/site-packages/django/db/migrations/recorder.py", line 56, in has_table
    tables = self.connection.introspection.table_names(cursor)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/introspection.py", line 48, in table_names
    return get_names(cursor)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/introspection.py", line 43, in get_names
    return sorted(ti.name for ti in self.get_table_list(cursor)
  File "/usr/local/lib/python3.9/site-packages/djongo/introspection.py", line 47, in get_table_list
    for c in cursor.db_conn.list_collection_names()
  File "/usr/local/lib/python3.9/site-packages/pymongo/database.py", line 863, in list_collection_names
    for result in self.list_collections(session=session, **kwargs)]
  File "/usr/local/lib/python3.9/site-packages/pymongo/database.py", line 825, in list_collections
    return self.__client._retryable_read(
  File "/usr/local/lib/python3.9/site-packages/pymongo/mongo_client.py", line 1460, in _retryable_read
    server = self._select_server(
  File "/usr/local/lib/python3.9/site-packages/pymongo/mongo_client.py", line 1278, in _select_server
    server = topology.select_server(server_selector)
  File "/usr/local/lib/python3.9/site-packages/pymongo/topology.py", line 241, in select_server
    return random.choice(self.select_servers(selector,
  File "/usr/local/lib/python3.9/site-packages/pymongo/topology.py", line 199, in select_servers
    server_descriptions = self._select_servers_loop(
  File "/usr/local/lib/python3.9/site-packages/pymongo/topology.py", line 215, in _select_servers_loop
    raise ServerSelectionTimeoutError(
pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 111] Connection refused, Timeout: 30s, Topology Description: <TopologyDescription id: 5f9ecaa5bbdc0433baa13966, topology_type: Single, servers: [<ServerDescription ('localhost', 27017) server_type: Unknown, rtt: None, error=AutoReconnect('localhost:27017: [Errno 111] Connection refused')>]>

此外,我还尝试创建一个Djongo模型并保存下来,以查看问题是否可能是特定于迁移的(基本上只是尝试使用djongo与mongo建立任何连接).

In addition, I've tried to create a Djongo model and save it to see if maybe the problem is specific to migrations (essentially just trying to make any connection to mongo using djongo).

models.py

models.py

from djongo import models

class Blog(models.Model):
    name = models.CharField(max_length=100)

test.py

b = Blog(name='test')
b.save()

返回以下错误:

The above exception was the direct cause of the following exception:
web_1      |
web_1      | Traceback (most recent call last):
web_1      |   File "/usr/local/lib/python3.9/site-packages/djongo/cursor.py", line 51, in execute
web_1      |     self.result = Query(
web_1      |   File "/usr/local/lib/python3.9/site-packages/djongo/sql2mongo/query.py", line 783, in __init__
web_1      |     self._query = self.parse()
web_1      |   File "/usr/local/lib/python3.9/site-packages/djongo/sql2mongo/query.py", line 884, in parse
web_1      |     raise exe from e
web_1      | djongo.exceptions.SQLDecodeError:
web_1      |
web_1      |    Keyword: None
web_1      |    Sub SQL: None
web_1      |    FAILED SQL: INSERT INTO "game_blog" ("name") VALUES (%(0)s)
web_1      |    Params: ['test']
web_1      |    Version: 1.3.3
web_1      |
web_1      | The above exception was the direct cause of the following exception:
web_1      |
web_1      | Traceback (most recent call last):
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
web_1      |     return self.cursor.execute(sql, params)
web_1      |   File "/usr/local/lib/python3.9/site-packages/djongo/cursor.py", line 59, in execute
web_1      |     raise db_exe from e
web_1      | djongo.database.DatabaseError
web_1      |
web_1      | The above exception was the direct cause of the following exception:
web_1      |
web_1      | Traceback (most recent call last):
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
web_1      |     response = get_response(request)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 179, in _get_response
web_1      |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
web_1      |     return self.dispatch(request, *args, **kwargs)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 98, in dispatch
web_1      |     return handler(request, *args, **kwargs)
web_1      |   File "/code/src/game/views.py", line 9, in get
web_1      |     b.save(using='mongo')
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 753, in save
web_1      |     self.save_base(using=using, force_insert=force_insert,
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 790, in save_base
web_1      |     updated = self._save_table(
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 895, in _save_table
web_1      |     results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 933, in _do_insert
web_1      |     return manager._insert(
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
web_1      |     return getattr(self.get_queryset(), name)(*args, **kwargs)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 1254, in _insert
web_1      |     return query.get_compiler(using=using).execute_sql(returning_fields)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1397, in execute_sql
web_1      |     cursor.execute(sql, params)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 98, in execute
web_1      |     return super().execute(sql, params)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 66, in execute
web_1      |     return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
web_1      |     return executor(sql, params, many, context)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
web_1      |     return self.cursor.execute(sql, params)
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
web_1      |     raise dj_exc_value.with_traceback(traceback) from exc_value
web_1      |   File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
web_1      |     return self.cursor.execute(sql, params)
web_1      |   File "/usr/local/lib/python3.9/site-packages/djongo/cursor.py", line 59, in execute
web_1      |     raise db_exe from e
web_1      | django.db.utils.DatabaseError

在此方面的任何帮助将不胜感激.

Any help on this would be greatly appreciated.

我已经尝试像> 一样编辑mongodb.conf

I have tried editing my mongodb.conf like this already.

推荐答案

根据此文档 settings.py 应具有 CLIENT 部分,其中应包含:

According to this document, the settings.py should have a CLIENT section which contains:

因此,请尝试将您的 settings.py 设置为:

So try setting your settings.py to:

DATABASE = {
    'default': {
        'ENGINE': 'djongo',
        'NAME': 'your-database-name',
        'CLIENT': {
            'host': 'mongodb://mongodb:27017',
            'username': 'root',
            'password': 'mongoadmin',
            'authSource': 'admin',
            'authMechanism': 'SCRAM-SHA-1',
        }
    }
}

这篇关于Django + Mongo + Docker获取pymongo.errors.ServerSelectionTimeoutError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-03 02:56
查看更多