Home > other >  Docker-compose - Cannot connect to Postgres
Docker-compose - Cannot connect to Postgres

Time:06-09

It looks like a common issue: can't connect to Postgres from a Django app in Docker Compose.

Actually, I tried several solution from the web, but probably I'm missing something I cannot see.

The error I got is:

django.db.utils.OperationalError: could not translate host name "db" to address: Try again

Where the "db" should be the name of the docker-compose service and which must setup in the .env.

My docker-compose.yml:

version: '3.3'
services:
  web:
    build: .
    container_name: drf_app
    volumes:
      - ./src:/drf
    links:
      - db:db
    ports:
      - 9090:8080
    env_file:
      - /.env
    depends_on:
      - db
  db:
    image: postgres:13-alpine
    environment:
      - POSTGRES_HOST_AUTH_METHOD=trust
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypass
      - POSTGRES_DB=mydb
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    ports:
      - 5432:5432

volumes:
  postgres_data:

My .env:

SQL_ENGINE=django.db.backends.postgresql
SQL_DATABASE=mydb
SQL_USER=myuser
SQL_PASSWORD=mypass
SQL_HOST=db #this one should match the service name
SQL_PORT=5432

As far as I know, web and db should automatically see each other in the same network, but this doesn't happens.

Inspecting the ip address with ifconfig on each container: django app has 172.17.0.2 and the db 172.19.0.2. They are not able to ping each other.

The result of docker ps command:

400879d47887   postgres:13-alpine   "docker-entrypoint.s…"   38 minutes ago   Up 38 minutes   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   backend_db_1

I really cannot figure out the issue, so am I missing something?

CodePudding user response:

You said in a comment:

The command I run is the following: docker run -it --entrypoint /bin/sh backend_web

Docker Compose creates several Docker resources, including a default network. If you separately docker run a container it doesn't see any of these resources. The docker run container is on the "default bridge network" and can't use present-day Docker networking capabilities, but the docker-compose container is on a separate "user-defined bridge network" named backend_default. That's why you're seeing a couple of the symptoms you do: the two networks have separate IPv4 CIDR ranges, and Docker's container DNS resolution only happens for the current network.

There's no reason to start a container with an interactive shell and then start your application within that (any more than you don't normally run python and then manually call main() from its REPL). Just start the entire application:

docker-compose up -d

If you do happen to need an interactive shell to debug your container setup or to run some manual tasks like database migrations, you can use docker-compose run for this. This honors most, but not all, of the settings in the docker-compose.yml file. In particular you can't docker-compose run an interactive shell and start your application from it, since it ignores ports:.

# Typical use: run database migrations
docker-compose run web \
  ./manage.py migrate

# For debugging: run an interactive shell
docker-compose run web bash

CodePudding user response:

I write this to save anyone in future from the same issue.

After countless tries, I started thinking that nothing was wrong from the pure docker perspective: I was right.

SOLUTION: My only suspect was related to the execution inside a Virtual Machine, so executing the same docker image on the host worked like a charm! The networking issue was related to the VM (VirtualBox Ubuntu 20.04)

I do not know if there is a way to work with docker-compose inside a VM, so any suggestion is appreciated.

  • Related