После перехода на postgresql - соединение сбрасывается коллегой

Согласно этому руководству я перешел на код postgresql.

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

Вот 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:

Все работало до редактирования DATABASES раздела.

Когда я бегу

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

Попробуйте использовать учетные данные db -

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

вы можете сделать это с помощью env-файла -

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

Невозможность подключения от web происходит до того, как db сообщает, что готов принимать соединения; depend_on: db заставляет web ждать запуска всего db контейнера, а не запуска Postgres внутри контейнера. Скорее всего, ваш web вызывает db раньше, чем он готов ответить.

В docker compose руководстве предлагается 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:

В статье руководства даже предупреждается о вашем точном сценарии (части, выделенные жирным шрифтом ):

Управление порядком запуска и выключения в Compose

Вы можете управлять порядком запуска и остановки сервисов с помощью атрибута depends_on. Compose всегда запускает и останавливает контейнеры в порядке зависимости, где зависимости определяются depends_on, links, volumes_from и network_mode: "service:...".

Хорошим примером того, как это можно использовать, является приложение, которому требуется доступ к базе данных. Если обе службы запущены с docker compose up, есть вероятность, что это не удастся, поскольку служба приложения может запуститься раньше службы базы данных и не найдет базу данных, способную обрабатывать ее SQL-запросы.

Управление запуском

.

При запуске Compose не ждет, пока контейнер будет «готов», а только пока он не будет запущен. Это может вызвать проблемы, если, например, у вас есть система реляционной базы данных, которая должна запустить свои собственные службы, прежде чем сможет обрабатывать входящие соединения.

Команда condition и соответствующая ей команда healthcheck взяты прямо из этого документа. Команда pg_isready поставляется в комплекте с вашим postgres образом.


То, что вы показали, возможно, изначально работало для автора этого руководства, и это может работать для других, если в их настройках Postgres удалось запустить достаточно быстро. Или, в их случае, web потребовалось больше времени для отправки запросов, чтобы Postgres успел завершить запуск и перехватить их.

Может возникнуть соблазн попытаться добавить начальный сон/ожидание/задержку в приложение web, чтобы дать ему время на инициализацию db, но безопаснее проверить и убедиться в этом. Также понятнее и проще отслеживать, если вы определяете условие зависимости в docker-compose.yml, а не в коде вашего приложения, которое не должно иметь дело с вопросами, связанными с настройкой среды.

Вернуться на верх