Tengo un contenedor de postgres, docker-compose.yml :
services: db: container_name: db expose: - "5432" ports: - 5432:5432 volumes: - postgres_data:/var/lib/postgresql/data/
Y un proyecto Django con settings.py :
DATABASES = { 'default': { 'HOST': os.environ.get('POSTGRES_HOST', '127.0.0.1') # etc } }
.env
POSTGRES_HOST_DJANGO=db
Cuando ejecuto mi aplicación django localmente con manage.py runserver 0.0.0.0:8000
, se conecta bien, usando el POSTGRES_HOST=127.0.0.1
predeterminado, porque .env no está cargado.
También ejecuto mi aplicación django en un contenedor a veces:
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
Sin embargo, usa el archivo .env y se conecta con POSTGRES_HOST=db
Si trato de conectar la aplicación django ejecutada localmente con POSTGRES_HOST=db
, falla:
django.db.utils.OperationalError: no se pudo traducir el nombre de host "db" a la dirección: nombre o servicio desconocido
Y si trato de ejecutar la aplicación django en un contenedor con POSTGRES_HOST=127.0.0.1
, falla de la misma manera.
¿Cómo puedo hacer que usen el mismo POSTGRES_HOST
?
El problema parece estar en la configuración de la red. no veo uno
El comportamiento predeterminado de docker-compose es que crea una red para cada archivo de redacción; de manera predeterminada, el nombre es el nombre de la carpeta con '_default'.
La aplicación Django está en una red diferente y Postgres está en una red diferente
Si su aplicación Django y sus contenedores de Postgres están en diferentes archivos docker-compose, el uso de nombres de contenedores para resolver hosts no funcionará (de manera predeterminada, se puede hacer con una configuración de red personalizada) ya que están en dos redes diferentes.
Como ha realizado un enlace de puerto, puede acceder directamente a Postgres proporcionando la IP privada de la máquina host y el puerto 5432 en el contenedor, de esta manera la comunicación se realiza a través de la red host.
Si encuentra la necesidad de hacer que los contenedores se comuniquen entre sí directamente, asegúrese de que estén en la misma red acoplable
Descubrí cómo hacerlo. No se trataba de hacer que usaran la misma variable, sino de hacer que leyeran diferentes variables en función de cómo se ejecutaba. Asi que:
desde 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
Y en .env :
POSTGRES_HOST=127.0.0.1
Ahora, cuando ejecuto localmente, con ./manage.py runserver
, usa el archivo .env y se conecta correctamente al contenedor db en 127.0.0.1:5342
Pero si ejecuto docker-compose up web
, aunque también lea el archivo .env, la variable de entorno proporcionada en el archivo de composición tiene prioridad y usa POSTGRES_HOST: db
y también se conecta al contenedor db.