-1

So, basically i have this docker-compose.yml config:

services:
  postgres:
    container_name: youtube_manager_postgres
    restart: always
    image: postgres:alpine
    environment:
      - POSTGRES_HOST_AUTH_METHOD=trust
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=qwerty123
      - POSTGRES_DB=ytmanager
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    ports:
      - "5432:5432"

  django:
    container_name: youtube_manager_django
    restart: always
    build:
      context: ../
      dockerfile: deploy/django/Dockerfile
    command: sh -c "poetry run python3 manage.py migrate &&
                    poetry run python3 manage.py collectstatic --no-input --clear &&
                    poetry run uwsgi --ini /etc/uwsgi.ini"
    ports:
      - "8000:8000"
    volumes:
      - staticfiles:/code/static
      - mediafiles:/code/media
    depends_on:
      - postgres

My Django's database preferences are:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'ytmanager',
        'USER': 'admin',
        'HOST': '0.0.0.0',
        'PASSWORD': 'qwerty123',
        'PORT': '5432',
    }
}

I wan't to use it in two ways: 1. Running docker-compose up -d postgres and then python3 manage.py runserver (actually, poetry run python3 manage.py runserver but for now it doesn't matter) during development. 2. Running docker-compose up during deployment.

For now, it works fine with the 1 option, but when I'm execution docker-compose up I'm getting an error:

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

If I'm changing Django database settings this way:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'ytmanager',
        'USER': 'admin',
        'HOST': '0.0.0.0',
        'PASSWORD': 'qwerty123',
        'PORT': '5432',
    }
}

Executing docker-compose up -d postgres and then python manage.py runserver causes an error:

django.db.utils.OperationalError: could not translate host name "postgres" to address: Temporary failure in name resolution

How could I properly config docker-compose.yml to use the same HOST in Django settings? (for example, 'HOST': '0.0.0.0' or 'HOST': 'postgres' for both options).

I've tried to use network_mode: host on my django and postgres services. It works fine, but is there any other way to solve a problem (for example, using networking settings? I've read docker-compose documentation on their website, but can't get what's going on there).

akhi1
  • 1,322
  • 1
  • 16
  • 25
  • 0.0.0.0 is a special IPv4 address that means "everywhere"; you wouldn't usually use it as the `HOST` setting you show. The Docker and non-Docker environments are different and you will need different `HOST` settings; an environment variable is a typical approach (default it to `localhost` for non-Docker but provide the alternate value in the `docker-compose.yml` file). – David Maze Jun 02 '20 at 10:15
  • Can I use `0.0.0.0` adress for both django and postgres services? – Vitaliy Diachkov Jun 02 '20 at 10:24

2 Answers2

0

I think you are mixing develop a production environments (by the way, second time you pasted your Django database settings probably you meant 'HOST': 'postgres')

So, if I'm not wrong:

  1. On development you want in your Django setting .py file: 'HOST': '0.0.0.0', since i think your are executing python manage.py runserver outside docker, keeping postgres in docker.

  2. On production you want the same in your Django setting .py file: 'HOST': '0.0.0.0', but to make it work you need 'HOST': 'postgres' (matching the name of the service in the compose file) and run everything on docker (executing the whole compose file as it is: docker-compose up). In this case, Django can't get access to '0.0.0.0' database host since it is running 'containerized' and that ip don't bind to any service, so it needs the ip or name of the service 'postgres'.

Posible solution:

In my opinion the solution is having two yml files to be called by Docker ( e.g. docker-compose -f docker-compose-development.yml up):

  • docker-compose-development.yml
  • docker-compose-production.yml

In each .yml file you can use different env variables or settings to cover differences between development and production in a clean way.

You can have a look at: https://github.com/pydanny/cookiecutter-django. It is a template Django project using Docker.

It follows "The Twelve Factors" app methodology: https://12factor.net/

In short:

  1. Environment variables are set in files under the .envs folder.
  2. in the compose .yml files you point to them in order to load the environment variables:
env_file:
     ./.envs/.production/.postgres
  1. Django settings .py files get access to the env variables using the django-environ package.
Marcos
  • 786
  • 7
  • 8
0

Before editing Django DB config, please ensure the following:

  • Both containers are running in the same network.

  • Postgres service is up and running in the container.

  • Service 'postgres' is accessible from the webapp container. For this you can login to the container and perform a ping test. docker exec -it containerID /bin/bash (in some cases /bin/sh) # to login to container

Solutions:

  1. Similar: Django connection to postgres by docker-compose
  2. For you to connect to DB using service name in Django, as per the documentation if the HOST and PORT keys are left out of the dictionary then Django will try connecting with the complete "NAME" as a SID.

Hope it helps

akhi1
  • 1,322
  • 1
  • 16
  • 25