2

I have a postgres container, docker-compose.yml:

services:
  db:
    container_name: db
    expose:
      - "5432"
    ports:
      - 5432:5432
    volumes:
      - postgres_data:/var/lib/postgresql/data/

And a django project with settings.py:

DATABASES = {
    'default': {
        'HOST': os.environ.get('POSTGRES_HOST', '127.0.0.1')
        # etc
    }
}

.env

POSTGRES_HOST_DJANGO=db

When I run my django app locally with manage.py runserver 0.0.0.0:8000 it connects fine, using the default POSTGRES_HOST=127.0.0.1, because .env isn't loaded.

I also run my django app in a container sometimes:

docker-compose.yml:

   web:
    #restart: unless-stopped
    build: .
    env_file: .env
    command: bash -c "cd /app/src/ && python manage.py runserver 0.0.0.0:8000
    volumes: 
      - .:/app
    ports:
      - 8000:8000
    links: 
      - db:db

However it uses the .env file and connects with POSTGRES_HOST=db

If I try to connect the locally run django app with POSTGRES_HOST=db it fails:

django.db.utils.OperationalError: could not translate host name "db" to address: Name or service not known

And if I try to run the django app in a container with POSTGRES_HOST=127.0.0.1, it fails in the same way.

How can I get them to use the same POSTGRES_HOST?

3
  • You don't; you need to set the environment variable differently in the different environments, which is what the .env file is for. Commented Jul 28, 2020 at 19:10
  • Are you saying it's impossible? Both read the same .env file so even if I had two .env files, how do I get the settings.py file to know which one to read? Commented Jul 29, 2020 at 22:15
  • Since you have two different setups and two different hostname schemes, you should be able to use two different .env files. You could specify an alternate env_file: in the docker-compose.yml file, or bind-mount a different config file into your container. Commented Jul 30, 2020 at 0:41

2 Answers 2

1

The problem seems to be in the network config. I don't see one.

The default behavior of docker-compose is that it creates a network for every compose file - by default the name is the folder name with '_default'.

Django App is in a different network and Postgres is in a different network

If your Django app and your Postgres containers are in different docker-compose files, using container names to resolve hosts will not work(by default, can be done with a custom network config) as they are in two different networks.

As you have done a port binding, you can directly access Postgres by giving host machine's private ip and port 5432 in the container, this way communication is happening through the host network.

If you find a need to make the containers talk to each other directly, make sure they are on the same docker network

Sign up to request clarification or add additional context in comments.

2 Comments

They are in the same docker-compose file. I have no problem with the containers talking to each other. The problem is when I try to run django locally, outside of a container, it will only connect to the postgres container using 127.0.0.1 and not db. I want a way for it to work for both ways of connecting: via web container, and running locally outside of a container
re your network comments, they are able to connect because all the ports are mapped out 5342:5342 etc. But this is obviously bad design as it exposes every service, so I've removed the port mapping and reconfigured my services to use a front and back end networks as suggested here: docker.com/blog/containerized-python-development-part-2 Thanks for prompting me in the right direction!
1

I figured out how to do it. It wasn't getting them to use the same variable, it was to get them to read different variables based on how it was run. So:

from docker-compose.yml

   web:
    build: .
    command: bash -c "cd /app/src/ && python manage.py runserver 0.0.0.0:8000
    env_file: .env
    environment:
      POSTGRES_HOST: db  # takes precendent over .env file

And in .env:

POSTGRES_HOST=127.0.0.1

Now, when I run locally, with ./manage.py runserver, it uses the .env file and connects to the db container properly at 127.0.0.1:5342

But if I run docker-compose up web, even though it also read the .env file, the environment variable provided in the compose file takes precedent and it uses POSTGRES_HOST: db and connects to the db container as well!

1 Comment

Good explanation. The key was that the POSTGRES_HOST: db takes precent over the .env file!!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.