Не удалось подключиться к серверу postgres в докере из докеризированного приложения - PullRequest
0 голосов
/ 29 декабря 2018

Я хотел бы запустить докеризованное приложение Django с докеризованным postgres.

Я запускаю докеризованное приложение Django с помощью:

docker run --rm --env-file /path/to/variables -d -p 8000:8000 django_app:test

Я запускаю докеризованное postgres с помощью:

docker run --rm -d --env-file /path/to/secrets/variables -p 5432:5432 \
    -v "$PWD/my-postgres.conf":/etc/postgresql/postgresql.conf \
    --mount src=/path/to/db/data,dst=/var/lib/postgresql/data,type=bind \
    postgres:alpine -c 'config_file=/etc/postgresql/postgresql.conf'

мой конфиг postgres - это конфиг по умолчанию, который предлагается в документации по докеру контейнера postgres .По сути, это файл конфигурации, который содержит listen_addresses = '*'

Я использую одинаковые переменные среды для обоих контейнеров:

DJANGO_SETTINGS_MODULE=settings.module
PROJECT_KEY=xxyyzzabcdefg
DB_ENGINE=django.db.backends.postgresql
POSTGRES_DB=db_name
POSTGRES_USER=db_user
POSTGRES_PASSWORD=verydifficultpassword
POSTGRES_HOST=localhost # I've also tried to use 0.0.0.0
POSTGRES_PORT=5432

Мой модуль настроек Django для базы данных:

 DATABASES = {
    'default': {
        'ENGINE': os.environ.get('DB_ENGINE'),
        'NAME': os.environ.get('POSTGRES_DB'),
        'USER': os.environ.get('POSTGRES_USER'),
        'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
        'HOST': os.environ.get('POSTGRES_HOST'),
        'PORT': os.environ.get('POSTGRES_PORT')
        }
  }

Однако я продолжаю получать:

django.db.utils.OperationalError: could not connect to server: Connection refused
    Is the server running on host "0.0.0.0" and accepting
    TCP/IP connections on port 5432?

Dockerfiles для моего приложения django выглядит так:

FROM python:alpine3.7
COPY --from=installer /app /app
# required for postgres
COPY --from=installer /usr/lib /usr/lib
COPY --from=installer /usr/local/bin /usr/local/bin
COPY --from=installer /usr/local/lib /usr/local/lib
ARG SETTINGS_MODULE
WORKDIR /app
ENTRYPOINT python manage.py migrate &&\
           python manage.py test &&\
           python manage.py create_default_groups &&\
           python manage.py set_screen_permissions &&\
           python manage.py create_test_users &&\
           python manage.py init_core &&\
           python manage.py runserver 0.0.0.0:8000

Еще один интересный факт заключается в том, что еслиЯ запускаю приложение локально python manage.py runserver и у меня запущен контейнер postgres, приложение, кажется, работает.

Может кто-нибудь помочь мне выяснить, почему я получаю отказ в соединении?Заранее спасибо!

Ответы [ 3 ]

0 голосов
/ 29 декабря 2018

В вашем Docker-контейнере с Django нет Postgres, работающего на localhost.вам нужно указать на Docker-контейнер Postgres, указав имя контейнера вместо localhost Кроме того, контейнер Postgres и ваше приложение должны находиться в одной сети.см. https://docs.docker.com/network/

Чтобы создать сеть, выполните:

docker network create --driver bridge my-network

Чтобы запустить Docker-контейнер в сети, используйте:

docker run --network my-network -it container_name

Для настройки Postgres в контейнере с Django:

POSTGRES_HOST=postgres-container-name
0 голосов
/ 29 декабря 2018

В вашем случае вы не указываете имена контейнеров.При установке POSTGRES_HOST=localhost вы указываете контейнеру django подключиться к себе.Что, естественно, приведет к сбою, так как в контейнере django отсутствует сервер postgres.

Два ваших контейнера используют сеть по умолчанию bridge (docker0).В мостовой сети имена контейнеров используются как имена хостов.

Это означает, что из вашего контейнера django вы можете получить доступ к контейнеру postgres, используя его имя в качестве имени хоста.

Чтобы иметь возможность подключиться к postgres из вашего приложения django, вам необходимо:

  1. Дать имена вашим контейнерам с помощью --name option.Пример: docker run --rm --name mypostgresdb -d ... postgres:alpine -c ...
  2. Сначала создайте контейнер postgres и дождитесь его загрузки.Затем создайте базу данных и пользователя / пароль.
  3. Только когда postgres работает, создайте контейнер django.Если контейнер postgres не работает, ваш контейнер django завершится сбоем, так как он пытается запустить миграцию в точке входа .
  4. Переменная POSTGRES_HOST env в вашем контейнере djangoдолжен получить в качестве значения имя контейнера postgres .Пример: POSTGRES_HOST=mypostgresdb

Чтобы проверить соединение с вашим контейнером postgres, вы можете пропинговать его из вашего контейнера django.

0 голосов
/ 29 декабря 2018

Просто используйте пользовательские мостовые сети.Во-первых, используйте свои знания, прочитав краткое объяснение различных типов сетей в Docker: https://docs.docker.com/network/bridge/

Во-вторых, определите свою собственную сеть

docker network create foo

Далее запустите свои контейнеры подключен к этой сети:

docker run --rm --env-file /path/to/variables -d --network foo django_app:test
docker run --rm -d ... --network foo postgres:alpine ...

Обратите внимание на обе команды --network foo.Также вам не нужно для предоставления портов в этом случае - внутри пользовательских сетей это делается автоматически:

Контейнеры, подключенные к одной и той же пользовательской мостовой сети, автоматически предоставляют все портыдруг другу, и нет портов для внешнего мира.Это позволяет контейнерам приложений легко взаимодействовать друг с другом, не открывая случайно доступ к внешнему миру.

В-третьих, присвойте своим контейнерам понятные человеку имена хостов с --name bar

docker run ... --network foo --name my-django django_app:test ...
docker run ... --network foo --name my-postgres postgres:alpine ...

И, наконец, исправьте строку подключения - измените с localhost на имя контейнера, например my-postgres:

...
POSTGRES_HOST=my-postgres
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...