skip to Main Content

I have a Django application which I’ve decided to setup in container as follows:

#docker-compose.yml
version: "3.9"
services:
  web:
    build: .
    command: python /code/manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - 8000:8000
    depends_on:
      - db
      
  db:
    image: postgres:13
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - "POSTGRES_HOST_AUTH_METHOD=trust"

volumes:
  postgres_data:

with database config in settings as follows

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "postgres",
        "USER": "postgres",
        "PASSWORD": "postgres",
        "HOST": "db",
        "PORT": 5432,
    }
}

And when I run the containers, the app works correctly with me being able to migrate and insert data into database.

However when I try to run the project outside of the container by following steps:

  1. python -m venv venv
  2. source venv/bin/activate
  3. pip install -r requirements.txt
  4. python manage.py runserver

I am getting an error:

Traceback (most recent call last):
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 244, in ensure_connection
    self.connect()
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 225, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/postgresql/base.py", line 203, in get_new_connection
    connection = Database.connect(**conn_params)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/psycopg2/__init__.py", line 122, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not translate host name "db" to address: Name or service not known


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

Traceback (most recent call last):
  File "/usr/lib64/python3.10/threading.py", line 1016, in _bootstrap_inner
    self.run()
  File "/usr/lib64/python3.10/threading.py", line 953, in run
    self._target(*self._args, **self._kwargs)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/core/management/commands/runserver.py", line 137, in inner_run
    self.check_migrations()
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/core/management/base.py", line 576, in check_migrations
    executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/executor.py", line 18, in __init__
    self.loader = MigrationLoader(self.connection)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/loader.py", line 58, in __init__
    self.build_graph()
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/loader.py", line 235, in build_graph
    self.applied_migrations = recorder.applied_migrations()
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/recorder.py", line 81, in applied_migrations
    if self.has_table():
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/migrations/recorder.py", line 57, in has_table
    with self.connection.cursor() as cursor:
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 284, in cursor
    return self._cursor()
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 260, in _cursor
    self.ensure_connection()
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 243, in ensure_connection
    with self.wrap_database_errors:
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 244, in ensure_connection
    self.connect()
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/base/base.py", line 225, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
    return func(*args, **kwargs)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/django/db/backends/postgresql/base.py", line 203, in get_new_connection
    connection = Database.connect(**conn_params)
  File "/home/jdoni/code/work/tasks/venv/lib64/python3.10/site-packages/psycopg2/__init__.py", line 122, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
django.db.utils.OperationalError: could not translate host name "db" to address: Name or service not known

I don’t really understand why django is unable to recognize the database host outside of container. Any ideas?

2

Answers


  1. You need to make the "db" container available locally, just map a local port, like this:

      db:
        image: postgres:13
        volumes:
          - postgres_data:/var/lib/postgresql/data/
        ports:
          - '5432:5432'
        environment:
          - "POSTGRES_HOST_AUTH_METHOD=trust"
    

    now you can check connection with:

    psql -h localhost -p 5432
    

    to access it from Django locally, you need to change a config to:

    DATABASES = {
        "default": {
            "ENGINE": "django.db.backends.postgresql",
            "NAME": "postgres",
            "USER": "postgres",
            "PASSWORD": "postgres",
            "HOST": "localhost",   # <----- HERE IS THE CHANGE
            "PORT": 5432,
        }
    }
    
    Login or Signup to reply.
  2. In your Django setup, I’d use an environment variable to specify the database location. You can set a default value for it, and I’d generally use a developer-friendly default.

    DATABASES = {
      "default": {
        "HOST": os.getenv("PGHOST", "localhost"),
        ...
      }
    }
    

    So long as your database container publishes ports:, you can use this with a host-based development setup

    docker-compose up -d db
    
    . ./venv/bin/activate
    ./manage.py runserver
    

    This means you need to set the environment variable in your Compose setup as well.

    version: '3.8'  # most recent 3.x Compose file version
    services:
      web:
        build: .
        ports:
          - 8000:8000
        depends_on:
          - db
        environment:   # add
          PGHOST: db   # add
        # (should not need volumes: or command: override)
    
      db:
        image: postgres:13
        volumes:
          - postgres_data:/var/lib/postgresql/data/
        environment:
          - "POSTGRES_HOST_AUTH_METHOD=trust"
        ports:            # add
          - '5432:5432'   # add
    
    volumes:
      postgres_data:
    

    If your host system is already using port 5432 for a different database, you need to change the first ports: number to something else that doesn’t conflict; the second must be fixed at the standard port 5432. You also will need to make the database port number configurable in the same way.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search