skip to Main Content

According to this tutorial I switched to postgresql code.

# django_project/settings.py
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.postgresql",
        "NAME": "postgres",
        "USER": "postgres",
        "PASSWORD": "postgres",
        "HOST": "db",  # set in docker-compose.yml
        "PORT": 5432,  # default postgres port
    }
}

Here is docker-compose.yml

# 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:

Everything worked before editing DATABASES section.

When I run

$ curl 127.0.0.1:8000
curl: (56) Recv failure: Connection reset by peer


$ sudo docker-compose logs
ch3-postresql-web-1  | Watching for file changes with StatReloader
ch3-postresql-web-1  | Exception in thread django-main-thread:
ch3-postresql-web-1  | Traceback (most recent call last):
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 244, in ensure_connection
ch3-postresql-web-1  |     self.connect()
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
ch3-postresql-web-1  |     return func(*args, **kwargs)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 225, in connect
ch3-postresql-web-1  |     self.connection = self.get_new_connection(conn_params)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
ch3-postresql-web-1  |     return func(*args, **kwargs)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/backends/postgresql/base.py", line 203, in get_new_connection
ch3-postresql-web-1  |     connection = Database.connect(**conn_params)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/psycopg2/__init__.py", line 122, in connect
ch3-postresql-web-1  |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
ch3-postresql-web-1  | psycopg2.OperationalError: connection to server at "db" (172.19.0.2), port 5432 failed: Connection timed out
ch3-postresql-web-1  |  Is the server running on that host and accepting TCP/IP connections?
ch3-postresql-web-1  | 
ch3-postresql-web-1  | 
ch3-postresql-web-1  | 
ch3-postresql-web-1  | 
ch3-postresql-web-1  | The above exception was the direct cause of the following exception:
ch3-postresql-web-1  | 
ch3-postresql-web-1  | 
ch3-postresql-web-1  | Traceback (most recent call last):
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/threading.py", line 1009, in _bootstrap_inner
ch3-postresql-web-1  |     self.run()
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/threading.py", line 946, in run
ch3-postresql-web-1  |     self._target(*self._args, **self._kwargs)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/utils/autoreload.py", line 64, in wrapper
ch3-postresql-web-1  |     fn(*args, **kwargs)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/core/management/commands/runserver.py", line 137, in inner_run
ch3-postresql-web-1  |     self.check_migrations()
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/core/management/base.py", line 576, in check_migrations
ch3-postresql-web-1  |     executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/migrations/executor.py", line 18, in __init__
ch3-postresql-web-1  |     self.loader = MigrationLoader(self.connection)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/migrations/loader.py", line 58, in __init__
ch3-postresql-web-1  |     self.build_graph()
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/migrations/loader.py", line 235, in build_graph
ch3-postresql-web-1  |     self.applied_migrations = recorder.applied_migrations()
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/migrations/recorder.py", line 81, in applied_migrations
ch3-postresql-web-1  |     if self.has_table():
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/migrations/recorder.py", line 57, in has_table
ch3-postresql-web-1  |     with self.connection.cursor() as cursor:
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
ch3-postresql-web-1  |     return func(*args, **kwargs)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 284, in cursor
ch3-postresql-web-1  |     return self._cursor()
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 260, in _cursor
ch3-postresql-web-1  |     self.ensure_connection()
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
ch3-postresql-web-1  |     return func(*args, **kwargs)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 243, in ensure_connection
ch3-postresql-web-1  |     with self.wrap_database_errors:
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
ch3-postresql-web-1  |     raise dj_exc_value.with_traceback(traceback) from exc_value
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 244, in ensure_connection
ch3-postresql-web-1  |     self.connect()
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
ch3-postresql-web-1  |     return func(*args, **kwargs)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/backends/base/base.py", line 225, in connect
ch3-postresql-web-1  |     self.connection = self.get_new_connection(conn_params)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 26, in inner
ch3-postresql-web-1  |     return func(*args, **kwargs)
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/django/db/backends/postgresql/base.py", line 203, in get_new_connection
ch3-postresql-web-1  |     connection = Database.connect(**conn_params)
ch3-postresql-db-1   | 
ch3-postresql-db-1   | 
ch3-postresql-web-1  |   File "/usr/local/lib/python3.10/site-packages/psycopg2/__init__.py", line 122, in connect
ch3-postresql-web-1  |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
ch3-postresql-web-1  | django.db.utils.OperationalError: connection to server at "db" (172.19.0.2), port 5432 failed: Connection timed out
ch3-postresql-web-1  |  Is the server running on that host and accepting TCP/IP connections?
ch3-postresql-web-1  | 
ch3-postresql-web-1  | 
ch3-postresql-db-1   | PostgreSQL Database directory appears to contain a database; Skipping initialization
ch3-postresql-db-1   | 
ch3-postresql-db-1   | 
ch3-postresql-db-1   | 2025-01-09 12:30:20.250 UTC [1] LOG:  starting PostgreSQL 13.18 (Debian 13.18-1.pgdg120+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
ch3-postresql-db-1   | 2025-01-09 12:30:20.251 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
ch3-postresql-db-1   | 2025-01-09 12:30:20.251 UTC [1] LOG:  listening on IPv6 address "::", port 5432
ch3-postresql-db-1   | 2025-01-09 12:30:20.257 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
ch3-postresql-db-1   | 2025-01-09 12:30:20.265 UTC [26] LOG:  database system was shut down at 2025-01-09 12:30:10 UTC
ch3-postresql-db-1   | 2025-01-09 12:30:20.284 UTC [1] LOG:  database system is ready to accept connections

2

Answers


  1. Try with using db Credentials –

    # 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_USER=postgres
          - POSTGRES_PASSWORD=postgres
          - POSTGRES_DB=postgres
    
    volumes:
      postgres_data:
    

    you can do with env file –

    db:
        image: postgres:13
        volumes:
          - postgres_data:/var/lib/postgresql/data/
        env_file:
          - ./.env.dev.db
    

    here is env

    #.env.dev.db
    POSTGRES_USER=postgres
    POSTGRES_PASSWORD=postgres
    POSTGRES_DB=postgres
    
    Login or Signup to reply.
  2. Notice that the failure to connect from web happens before db reports that it’s ready to accept connections. That’s because depend_on: db only forces web to wait for the whole db container to start, not for postgres inside the container to start.
    As per the example in the docker compose manual, you need to run a bit more detailed check in the depend_on:

    # 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: 
              condition: service_healthy
      db:
        image: postgres:13
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
          interval: 10s
          retries: 5
          start_period: 30s
          timeout: 10s
        volumes:
          - postgres_data:/var/lib/postgresql/data/
        environment:
          - "POSTGRES_HOST_AUTH_METHOD=trust"
    
    volumes:
      postgres_data:
    

    The manual entry even warns about your exact scenario (the part in bold):

    Control startup and shutdown order in Compose

    You can control the order of service startup and shutdown with the depends_on attribute. Compose always starts and stops containers in dependency order, where dependencies are determined by depends_on, links, volumes_from, and network_mode: "service:...".

    A good example of when you might use this is an application which needs to access a database. If both services are started with docker compose up, there is a chance this will fail since the application service might start before the database service and won’t find a database able to handle its SQL statements.

    Control startup

    On startup, Compose does not wait until a container is "ready", only until it’s running. This can cause issues if, for example, you have a relational database system that needs to start its own services before being able to handle incoming connections.

    The condition and its corresponding healthcheck command are straight from that doc. The pg_isready comes bundled inside your postgres image.

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