Django + Mongo + Docker getting pymongo.errors.ServerSelectionTimeoutError

眉间皱痕 提交于 2021-02-10 16:17:16

问题


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

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

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

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

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())

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')>]>

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

from djongo import models

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

test.py

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

That returns the following error:

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.

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


回答1:


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

A set of key-value pairs that will be passed directly to MongoClient as kwargs while creating a new client connection.

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',
        }
    }
}


来源:https://stackoverflow.com/questions/64616386/django-mongo-docker-getting-pymongo-errors-serverselectiontimeouterror

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!