After switching to postgresql - connection reset by peer

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

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

The failure to connect from web happens before db reports that it's ready to accept connections; depend_on: db only forces web to wait for the whole db container to start, not for Postgres inside the container to start. Your web is likely calling db before it's ready to answer.

The docker compose manual suggests it's best to make depend_on check the service status:

# 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 parts 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.


What you showed might've originally worked for the author of that tutorial and it might work for others if on their setup Postgres managed to start up fast enough. Or, in their case web took longer before sending the requests, long enough for Postgres to finish starting up and catch them.

It might be tempting to try to add an initial sleep/wait/delay in your web app, to let it give some time for the db to initialise but it's safer to properly check and make sure. It's also clearer and easier to track if you define the dependency condition in the docker-compose.yml rather than inside your app code, which shouldn't have to deal with matters related to environment setup.

Back to Top