Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

django.db.utils.OperationalError: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory #1073

Open
karambaq opened this issue Sep 15, 2023 · 1 comment

Comments

@karambaq
Copy link

I've docker-compose configuration for django and postgres, it works fine. However, when I'm trying to run pytest inside a django container it fails with an error:

pytest apps/service/tests/test_api.py::TestCreate::test_new
====================================================================== test session starts =======================================================================
platform linux -- Python 3.8.18, pytest-7.4.1, pluggy-1.3.0
django: settings: project.settings.local (from env)
rootdir: /app/code
configfile: pytest.ini
plugins: mock-3.11.1, django-4.5.2, Faker-19.6.1, celery-4.4.2
collected 1 item

apps/service/tests/test_api.py E                                                                                                                           [100%]

============================================================================= ERRORS =============================================================================
__________________________________________________ ERROR at setup of TestCreate.test_new __________________________________________________

self = <django.db.backends.postgresql.base.DatabaseWrapper object at 0xffff71cedf70>

    @async_unsafe
    def ensure_connection(self):
        """Guarantee that a connection to the database is established."""
        if self.connection is None:
            with self.wrap_database_errors:
>               self.connect()

/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:219:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:200: in connect
    self.connection = self.get_new_connection(conn_params)
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/postgresql/base.py:187: in get_new_connection
    connection = Database.connect(**conn_params)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

dsn = 'dbname=postgres', connection_factory = None, cursor_factory = None, kwargs = {'database': 'postgres'}, kwasync = {}

    def connect(dsn=None, connection_factory=None, cursor_factory=None, **kwargs):
        """
        Create a new database connection.

        The connection parameters can be specified as a string:

            conn = psycopg2.connect("dbname=test user=postgres password=secret")

        or using a set of keyword arguments:

            conn = psycopg2.connect(database="test", user="postgres", password="secret")

        Or as a mix of both. The basic connection parameters are:

        - *dbname*: the database name
        - *database*: the database name (only as keyword argument)
        - *user*: user name used to authenticate
        - *password*: password used to authenticate
        - *host*: database host address (defaults to UNIX socket if not provided)
        - *port*: connection port number (defaults to 5432 if not provided)

        Using the *connection_factory* parameter a different class or connections
        factory can be specified. It should be a callable object taking a dsn
        argument.

        Using the *cursor_factory* parameter, a new default cursor factory will be
        used by cursor().

        Using *async*=True an asynchronous connection will be created. *async_* is
        a valid alias (for Python versions where ``async`` is a keyword).

        Any other keyword parameter will be passed to the underlying client
        library: the list of supported parameters depends on the library version.

        """
        kwasync = {}
        if 'async' in kwargs:
            kwasync['async'] = kwargs.pop('async')
        if 'async_' in kwargs:
            kwasync['async_'] = kwargs.pop('async_')

        if dsn is None and not kwargs:
            raise TypeError('missing dsn and no parameters')

        dsn = _ext.make_dsn(dsn, **kwargs)
>       conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
E       psycopg2.OperationalError: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory
E       	Is the server running locally and accepting connections on that socket?

/usr/local/lib/python3.8/site-packages/psycopg2/__init__.py:127: OperationalError

The above exception was the direct cause of the following exception:

self = <django.db.backends.postgresql.base.DatabaseWrapper object at 0xffff7f398d30>

    @contextmanager
    def _nodb_cursor(self):
        try:
>           with super()._nodb_cursor() as cursor:

/usr/local/lib/python3.8/site-packages/django/db/backends/postgresql/base.py:301:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.8/contextlib.py:113: in __enter__
    return next(self.gen)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:620: in _nodb_cursor
    with conn.cursor() as cursor:
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:259: in cursor
    return self._cursor()
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:235: in _cursor
    self.ensure_connection()
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:219: in ensure_connection
    self.connect()
/usr/local/lib/python3.8/site-packages/django/db/utils.py:90: in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:219: in ensure_connection
    self.connect()
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:200: in connect
    self.connection = self.get_new_connection(conn_params)
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/postgresql/base.py:187: in get_new_connection
    connection = Database.connect(**conn_params)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

dsn = 'dbname=postgres', connection_factory = None, cursor_factory = None, kwargs = {'database': 'postgres'}, kwasync = {}

    def connect(dsn=None, connection_factory=None, cursor_factory=None, **kwargs):
        """
        Create a new database connection.

        The connection parameters can be specified as a string:

            conn = psycopg2.connect("dbname=test user=postgres password=secret")

        or using a set of keyword arguments:

            conn = psycopg2.connect(database="test", user="postgres", password="secret")

        Or as a mix of both. The basic connection parameters are:

        - *dbname*: the database name
        - *database*: the database name (only as keyword argument)
        - *user*: user name used to authenticate
        - *password*: password used to authenticate
        - *host*: database host address (defaults to UNIX socket if not provided)
        - *port*: connection port number (defaults to 5432 if not provided)

        Using the *connection_factory* parameter a different class or connections
        factory can be specified. It should be a callable object taking a dsn
        argument.

        Using the *cursor_factory* parameter, a new default cursor factory will be
        used by cursor().

        Using *async*=True an asynchronous connection will be created. *async_* is
        a valid alias (for Python versions where ``async`` is a keyword).

        Any other keyword parameter will be passed to the underlying client
        library: the list of supported parameters depends on the library version.

        """
        kwasync = {}
        if 'async' in kwargs:
            kwasync['async'] = kwargs.pop('async')
        if 'async_' in kwargs:
            kwasync['async_'] = kwargs.pop('async_')

        if dsn is None and not kwargs:
            raise TypeError('missing dsn and no parameters')

        dsn = _ext.make_dsn(dsn, **kwargs)
>       conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
E       django.db.utils.OperationalError: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory
E       	Is the server running locally and accepting connections on that socket?

/usr/local/lib/python3.8/site-packages/psycopg2/__init__.py:127: OperationalError

During handling of the above exception, another exception occurred:

self = <django.db.backends.postgresql.base.DatabaseWrapper object at 0xffff71593ca0>

    @async_unsafe
    def ensure_connection(self):
        """Guarantee that a connection to the database is established."""
        if self.connection is None:
            with self.wrap_database_errors:
>               self.connect()

/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:219:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:200: in connect
    self.connection = self.get_new_connection(conn_params)
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/postgresql/base.py:187: in get_new_connection
    connection = Database.connect(**conn_params)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

dsn = 'dbname=test_project', connection_factory = None, cursor_factory = None, kwargs = {'database': 'test_project'}, kwasync = {}

    def connect(dsn=None, connection_factory=None, cursor_factory=None, **kwargs):
        """
        Create a new database connection.

        The connection parameters can be specified as a string:

            conn = psycopg2.connect("dbname=test user=postgres password=secret")

        or using a set of keyword arguments:

            conn = psycopg2.connect(database="test", user="postgres", password="secret")

        Or as a mix of both. The basic connection parameters are:

        - *dbname*: the database name
        - *database*: the database name (only as keyword argument)
        - *user*: user name used to authenticate
        - *password*: password used to authenticate
        - *host*: database host address (defaults to UNIX socket if not provided)
        - *port*: connection port number (defaults to 5432 if not provided)

        Using the *connection_factory* parameter a different class or connections
        factory can be specified. It should be a callable object taking a dsn
        argument.

        Using the *cursor_factory* parameter, a new default cursor factory will be
        used by cursor().

        Using *async*=True an asynchronous connection will be created. *async_* is
        a valid alias (for Python versions where ``async`` is a keyword).

        Any other keyword parameter will be passed to the underlying client
        library: the list of supported parameters depends on the library version.

        """
        kwasync = {}
        if 'async' in kwargs:
            kwasync['async'] = kwargs.pop('async')
        if 'async_' in kwargs:
            kwasync['async_'] = kwargs.pop('async_')

        if dsn is None and not kwargs:
            raise TypeError('missing dsn and no parameters')

        dsn = _ext.make_dsn(dsn, **kwargs)
>       conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
E       psycopg2.OperationalError: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory
E       	Is the server running locally and accepting connections on that socket?

/usr/local/lib/python3.8/site-packages/psycopg2/__init__.py:127: OperationalError

The above exception was the direct cause of the following exception:

request = <SubRequest '_django_db_marker' for <Function test_new>>

    @pytest.fixture(autouse=True)
    def _django_db_marker(request) -> None:
        """Implement the django_db marker, internal to pytest-django."""
        marker = request.node.get_closest_marker("django_db")
        if marker:
>           request.getfixturevalue("_django_db_helper")

/usr/local/lib/python3.8/site-packages/pytest_django/plugin.py:465:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/usr/local/lib/python3.8/site-packages/pytest_django/fixtures.py:122: in django_db_setup
    db_cfg = setup_databases(
/usr/local/lib/python3.8/site-packages/django/test/utils.py:179: in setup_databases
    connection.creation.create_test_db(
/usr/local/lib/python3.8/site-packages/django/db/backends/base/creation.py:57: in create_test_db
    self._create_test_db(verbosity, autoclobber, keepdb)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/creation.py:191: in _create_test_db
    with self._nodb_cursor() as cursor:
/usr/local/lib/python3.8/contextlib.py:113: in __enter__
    return next(self.gen)
/usr/local/lib/python3.8/site-packages/django/db/backends/postgresql/base.py:319: in _nodb_cursor
    with conn.cursor() as cursor:
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:259: in cursor
    return self._cursor()
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:235: in _cursor
    self.ensure_connection()
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:219: in ensure_connection
    self.connect()
/usr/local/lib/python3.8/site-packages/django/db/utils.py:90: in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:219: in ensure_connection
    self.connect()
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/base/base.py:200: in connect
    self.connection = self.get_new_connection(conn_params)
/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py:33: in inner
    return func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/django/db/backends/postgresql/base.py:187: in get_new_connection
    connection = Database.connect(**conn_params)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

dsn = 'dbname=test_project', connection_factory = None, cursor_factory = None, kwargs = {'database': 'test_project'}, kwasync = {}

    def connect(dsn=None, connection_factory=None, cursor_factory=None, **kwargs):
        """
        Create a new database connection.

        The connection parameters can be specified as a string:

            conn = psycopg2.connect("dbname=test user=postgres password=secret")

        or using a set of keyword arguments:

            conn = psycopg2.connect(database="test", user="postgres", password="secret")

        Or as a mix of both. The basic connection parameters are:

        - *dbname*: the database name
        - *database*: the database name (only as keyword argument)
        - *user*: user name used to authenticate
        - *password*: password used to authenticate
        - *host*: database host address (defaults to UNIX socket if not provided)
        - *port*: connection port number (defaults to 5432 if not provided)

        Using the *connection_factory* parameter a different class or connections
        factory can be specified. It should be a callable object taking a dsn
        argument.

        Using the *cursor_factory* parameter, a new default cursor factory will be
        used by cursor().

        Using *async*=True an asynchronous connection will be created. *async_* is
        a valid alias (for Python versions where ``async`` is a keyword).

        Any other keyword parameter will be passed to the underlying client
        library: the list of supported parameters depends on the library version.

        """
        kwasync = {}
        if 'async' in kwargs:
            kwasync['async'] = kwargs.pop('async')
        if 'async_' in kwargs:
            kwasync['async_'] = kwargs.pop('async_')

        if dsn is None and not kwargs:
            raise TypeError('missing dsn and no parameters')

        dsn = _ext.make_dsn(dsn, **kwargs)
>       conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
E       django.db.utils.OperationalError: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory
E       	Is the server running locally and accepting connections on that socket?

/usr/local/lib/python3.8/site-packages/psycopg2/__init__.py:127: OperationalError
--------------------------------------------------------------------- Captured stderr setup ----------------------------------------------------------------------


/usr/local/lib/python3.8/site-packages/django/db/backends/postgresql/base.py:304: RuntimeWarning: Normally Django will use a connection to the 'postgres' database to avoid running initialization queries against the production database when it's not needed (for example, when running tests). Django was unable to create a connection to the 'postgres' database and will use the first PostgreSQL database instead.
  warnings.warn(
==================================================================== short test summary info =====================================================================
ERROR apps/service/tests/test_api.py::TestCreate::test_new - django.db.utils.OperationalError: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: No such file or directory
======================================================================== 1 error in 5.25s ========================================================================

This is actually true, there is no such file in django container, it's inside the psql container, but I don't understand what to do with this error. I checked that test database created.

I can fix this error if add this fixture in conftest.py

import pytest

@pytest.fixture()
def django_db_setup():
    pass

But using this approach it using my actual database, not the "test_*" one.

I don't think that this is docker-compose problem because other than tests it works fine.

@karambaq
Copy link
Author

I found the solution, but not sure that if this is the right one.

DATABASES = {
    'default': {
        'ENGINE': 'django.contrib.gis.db.backends.postgis',
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USERNAME'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': os.environ.get('DB_HOSTNAME'),
        'PORT': os.environ.get('DB_PORT'),
    },
    LOG_DB: {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('LOG_DB_NAME'),
        'USER': os.environ.get('LOG_DB_USERNAME'),
        'PASSWORD': os.environ.get('LOG_DB_PASSWORD'),
        'HOST': os.environ.get('LOG_DB_HOSTNAME'),
        'PORT': os.environ.get('LOG_DB_PORT'),
    }
}

In my settings I had two databases in DATABASES dict, after I comment out the second one, all works as expected. But how can I specify to use only first database for pytest?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant