Redes y conectividad
Esta guía cubre dos formas comunes de conectarse a PostgreSQL ejecutándose en Docker:
- De contenedor a contenedor: Conéctate desde el contenedor de tu aplicación a PostgreSQL a través de una red privada de Docker. No es necesario exponer ningún puerto al host.
- De host a contenedor: Conéctate desde tu computadora portátil o máquina de desarrollo usando
localhosty un puerto publicado.
Requisito previo: Esta guía asume que tienes PostgreSQL ejecutándose con almacenamiento persistente. Si no es así, sigue primero la guía Configuración inmediata y persistencia de datos.
Acceso de red interna (de contenedor a contenedor)
Cuando tu aplicación se ejecuta en otro contenedor, conectarse a PostgreSQL a través de una red puente (bridge network) definida por el usuario es el enfoque recomendado. Esta configuración proporciona resolución DNS automática, por lo que tu aplicación puede conectarse a PostgreSQL utilizando el nombre del contenedor como nombre de host (hostname), sin necesidad de rastrear direcciones IP.
¿Por qué no usar la red puente predeterminada? Aunque los contenedores en la red puente predeterminada pueden comunicarse, solo pueden hacerlo por dirección IP. Dado que las direcciones IP de los contenedores cambian cuando estos se reinician, esto requeriría actualizar las cadenas de conexión de PostgreSQL cada vez. Las redes puente definidas por el usuario resuelven esto al proporcionar resolución DNS automática, lo que garantiza que tus cadenas de conexión de PostgreSQL se mantengan estables incluso si los contenedores se reinician y reciben nuevas direcciones IP.
Aquí tienes una comparación rápida:
NoteLos siguientes ejemplos muestran la diferencia en el enfoque. Para probar esto en la práctica, sigue primero los pasos de esta guía para configurar contenedores en las redes adecuadas.
Con la red puente predeterminada, primero tendrías que buscar la dirección IP:
# Obtener la dirección IP del contenedor (cambia al reiniciar)
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' postgres-dev
# Salida: 172.17.0.2
# Luego conectarse usando esa dirección IP desde otro contenedor
# (No se necesita la bandera --network: los contenedores usan la red puente por defecto)
docker run --rm -it \
-e PGPASSWORD=mysecretpassword \
postgres:18 \
psql -h 172.17.0.2 -U postgresCon una red definida por el usuario, simplemente usas el nombre del contenedor:
# El nombre del contenedor funciona directamente, no se requiere buscar la IP
docker run --rm -it \
--network my-app-net \
-e PGPASSWORD=mysecretpassword \
postgres:18 \
psql -h postgres-dev -U postgresPaso 1: Crear una red definida por el usuario
docker network create my-app-net
# Salida de ejemplo
ab7f984be43a0ca15534a9ee568716ddbe869a5875077fad3ef3192e3af7d288
docker network ls
# Salida
ab7f984be43a my-app-net bridge localPaso 2: Ejecutar PostgreSQL en esa red (sin publicación de puertos)
Ten en cuenta que no hay -p 5432:5432 aquí. Esto mantiene a PostgreSQL interno a Docker y no accesible desde la máquina host, lo cual es más seguro para entornos de producción.
docker run -d --name postgres-dev \
--network my-app-net \
-e POSTGRES_PASSWORD=mysecretpassword \
-v postgres_data:/var/lib/postgresql \
postgres:18
# Salida
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6d351ed89efc postgres:18 "docker-entrypoint.s…" 9 seconds ago Up 8 seconds 5432/tcp postgres-devPaso 3: Conectarse desde otro contenedor usando el nombre del contenedor Postgres
Puedes probar la conectividad con un contenedor cliente psql temporal:
docker run --rm -it \
--network my-app-net \
-e PGPASSWORD=mysecretpassword \
postgres:18 \
psql -h postgres-dev -U postgresPunto clave: -h postgres-dev funciona porque el DNS de Docker resuelve el nombre del contenedor en una red definida por el usuario. El nombre del contenedor actúa como el nombre de host (hostname).
Ejemplos de cadenas de conexión
Al conectarte desde el contenedor de tu aplicación, utiliza estas cadenas de conexión de PostgreSQL:
Formato URI de PostgreSQL: Este es el formato estándar de URI de conexión de PostgreSQL que combina todos los parámetros de conexión en una sola cadena, ampliamente compatible con clientes y bibliotecas de PostgreSQL.
postgresql://postgres:mysecretpassword@postgres-dev:5432/postgresEste comando demuestra cómo pasar una cadena de conexión URI de PostgreSQL como una variable de entorno a un contenedor, que luego tu aplicación puede leer para conectarse a la base de datos.
Ejemplo de uso en un comando docker run:
docker run --rm -it \ --network my-app-net \ -e DATABASE_URL="postgresql://postgres:mysecretpassword@postgres-dev:5432/postgres" \ alpine:latest \ sh -c 'echo "DATABASE_URL is set to: $DATABASE_URL"'Parámetros de conexión de PostgreSQL: Este formato utiliza pares clave-valor separados por espacios, que muchas bibliotecas de clientes de PostgreSQL aceptan como alternativa al formato URI.
host=postgres-dev port=5432 user=postgres password=mysecretpassword dbname=postgresEjemplo de uso en código de aplicación (Python con psycopg2):
conn = psycopg2.connect( host="postgres-dev", port=5432, user="postgres", password="mysecretpassword", dbname="postgres" )Conectarse a una base de datos específica: Reemplaza el nombre de la base de datos en la cadena de conexión para conectarte a una base de datos específica en lugar de la base de datos predeterminada
postgres. Si creaste una base de datos personalizada (por ejemplo,testdb), usa:postgresql://postgres:mysecretpassword@postgres-dev:5432/testdbEjemplo con SSL desactivado (común en redes Docker): Agrega
?sslmode=disablea la cadena de conexión cuando te conectes dentro de una red privada de Docker donde no se requiere cifrado SSL.postgresql://postgres:mysecretpassword@postgres-dev:5432/testdb?sslmode=disable
NoteEn estos ejemplos se utiliza el puerto predeterminado
5432. Si te estás conectando a una instancia de PostgreSQL diferente o has cambiado el puerto, update la cadena de conexión en consecuencia. El nombre del contenedor (postgres-dev) es resuelto por el DNS de Docker a la dirección IP del contenedor en la red.
Conectarse desde el Host (acceso externo)
Para conectarte a PostgreSQL desde tu máquina host utilizando herramientas como psql, pgAdmin, DBeaver o scripts de administración de bases de datos, necesitas publicar el puerto de PostgreSQL (5432) en el host. Esto permite que las herramientas externas accedan al contenedor de PostgreSQL.
Exponer Postgres solo a localhost (recomendado para desarrollo)
Esto se asocia a 127.0.0.1 para que solo sea accesible desde tu máquina local, no desde otros dispositivos en tu red. Esta es la opción más segura para el desarrollo.
docker run -d --name postgres-dev \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 127.0.0.1:5432:5432 \
-v postgres_data:/var/lib/postgresql \
postgres:18Ahora conéctate desde tu host:
- Host:
localhosto127.0.0.1 - Puerto:
5432
Si tienes psql instalado en tu host:
psql -h localhost -p 5432 -U postgresSe te pedirá la contraseña. Alternativamente, puedes usar la variable de entorno PGPASSWORD:
PGPASSWORD=mysecretpassword psql -h localhost -p 5432 -U postgresConectarse con herramientas GUI de PostgreSQL
Las herramientas GUI populares de PostgreSQL pueden conectarse utilizando estos detalles de conexión comunes: Host: localhost, Puerto: 5432, Usuario: postgres, Base de datos: postgres (o el nombre de tu base de datos).
- pgAdmin: Una plataforma de desarrollo y administración de PostgreSQL basada en la web
- DBeaver: Una herramienta de base de datos universal que admite PostgreSQL y muchas otras bases de datos. Selecciona PostgreSQL como el tipo de conexión
- TablePlus: Una herramienta de administración de bases de datos moderna y nativa para macOS y Windows con una interfaz limpia
Todas las herramientas te pedirán la contraseña que estableciste con POSTGRES_PASSWORD.
Exponer Postgres a todas las interfaces de red (usar con precaución)
Para permitir conexiones desde otros dispositivos en tu red, utiliza -p 5432:5432 en lugar de -p 127.0.0.1:5432:5432. Esto asocia PostgreSQL a todas las interfaces de red de tu host, haciéndolo accesible desde cualquier dispositivo que pueda llegar a tu host, no solo desde localhost.
docker run -d --name postgres-dev \
-e POSTGRES_PASSWORD=mysecretpassword \
-p 5432:5432 \
-v postgres_data:/var/lib/postgresql \
postgres:18WarningExponer PostgreSQL a todas las interfaces de red (
0.0.0.0:5432) lo hace accesible desde cualquier dispositivo que pueda llegar a tu host. Utiliza esto únicamente en entornos de red de confianza o detrás de un firewall. Para producción, considera usar un proxy inverso o una VPN en su lugar.
Consideraciones de seguridad de PostgreSQL para el acceso externo
Al exponer PostgreSQL al acceso externo, sigue estas prácticas de seguridad específicas de PostgreSQL:
- Evita usar el superusuario
postgres: El usuariopostgrespredeterminado tiene todos los privilegios de la base de datos. Crea usuarios dedicados solo con los permisos que tu aplicación necesita. - Usa contraseñas seguras: Las contraseñas de PostgreSQL deben ser complejas. Considera usar variables de entorno o gestión de secretos en lugar de escribir contraseñas en código duro (hardcoding).
- Limita la exposición de red: Asociar a
127.0.0.1(solo localhost) es más seguro que exponer a todas las interfaces (0.0.0.0). - Considera SSL/TLS: Para producción, configura PostgreSQL para requerir conexiones SSL. La guía Configuración avanzada e inicialización muestra cómo configurar los ajustes de PostgreSQL.
- Crea usuarios específicos de la aplicación: Usa scripts de inicialización para crear usuarios con privilegios limitados. Por ejemplo, un usuario de solo lectura para informes o un usuario que solo pueda acceder a bases de datos específicas.
La guía Configuración avanzada e inicialización muestra cómo usar scripts de inicialización para crear usuarios y roles automáticamente.
Uso de Docker Compose para redes
Docker Compose crea automáticamente una red para tus servicios, simplificando la configuración de red. Aquí tienes un ejemplo que combina el acceso interno y externo:
services:
db:
image: postgres:18
container_name: postgres-dev
environment:
POSTGRES_PASSWORD: mysecretpassword
volumes:
- postgres_data:/var/lib/postgresql
ports:
- "127.0.0.1:5432:5432" # Exponer solo a localhost
networks:
- app-network
app:
build: ./my-app
environment:
DATABASE_URL: postgresql://postgres:mysecretpassword@db:5432/mydb
networks:
- app-network
depends_on:
- db
volumes:
postgres_data:
networks:
app-network:
driver: bridgeEn esta configuración centrada en PostgreSQL:
- El servicio
appse conecta a PostgreSQL utilizando el nombre del servicio (db) como el nombre de host en la cadena de conexión - PostgreSQL es accesible desde tu host en
localhost:5432para herramientas externas - Ambos servicios están aislados en una red personalizada, lo que proporciona seguridad a nivel de red
- La directiva
depends_ongarantiza que PostgreSQL se inicie antes que tu aplicación
Detalles de conexión de PostgreSQL para el servicio app:
- Nombre de host:
db(resuelto por el DNS de Docker) - Puerto:
5432(puerto predeterminado de PostgreSQL) - Base de datos:
mydb(como se especifica en la cadena de conexión) - Usuario:
postgres(o un usuario personalizado que hayas creado)
NoteDocker Compose crea automáticamente una red para tu proyecto. Los servicios pueden comunicarse entre sí por nombre de servicio sin una configuración de red explícita, pero definir una red personalizada te da más control. Para PostgreSQL, esto significa que tu aplicación siempre puede conectarse usando el nombre del servicio, independientemente de los reinicios de contenedores o los cambios de IP.
Resolución de problemas
Esta sección cubre problemas comunes de conexión de PostgreSQL y sus soluciones al trabajar con redes Docker.
"Could not translate host name postgres-dev"
- Ambos contenedores deben estar en la misma red de Docker (
my-app-net). - Verifica que la red exista:
docker network ls - Verifica en qué red está un contenedor:
docker inspect postgres-dev | grep NetworkMode - Asegúrate de estar usando una red definida por el usuario, no la red puente predeterminada
"Connection refused" o "could not connect to server"
PostgreSQL aún podría estar inicializándose: PostgreSQL tarda unos segundos en iniciarse e inicializar el clúster de la base de datos. Espera entre 5 y 10 segundos después del inicio del contenedor y vuelve a intentarlo.
Verifica si el contenedor de PostgreSQL se está ejecutando:
docker ps --filter name=postgres-devRevisa los registros de PostgreSQL en busca de errores de inicialización o conexión:
docker logs postgres-devBusca mensajes como "database system is ready to accept connections" para confirmar que PostgreSQL se ha iniciado por completo.
Verifica que el mapeo de puertos sea correcto:
docker port postgres-devEsto debería mostrar
5432/tcp -> 127.0.0.1:5432(o0.0.0.0:5432si está asociado a todas las interfaces).Prueba la conectividad de PostgreSQL desde el interior del contenedor:
docker exec -it postgres-dev psql -U postgres -c "SELECT version();"Si esto funciona pero las conexiones externas fallan, el problema es con la publicación de puertos, no con PostgreSQL en sí.
"Password authentication failed" o "FATAL: password authentication failed for user"
- Confirma la contraseña: Verifica que estés usando la misma contraseña establecida en
POSTGRES_PASSWORDcuando iniciaste el contenedor. - Volumen existente con credenciales antiguas: Si reutilizaste un volumen existente, la contraseña de la inicialización original sigue vigente. La variable de entorno
POSTGRES_PASSWORDsolo establece la contraseña durante la primera inicialización de la base de datos. Para restablecerla:- Elimina el volumen:
docker volume rm postgres_data - O conéctate con la contraseña antigua
- O cambia la contraseña después de conectarte:
ALTER USER postgres WITH PASSWORD 'newpassword';
- Elimina el volumen:
- Intenta conectarte con solicitud de contraseña:
psql -h localhost -U postgres -W(la bandera-Wfuerza una solicitud de contraseña) - Usa la variable de entorno PGPASSWORD:
PGPASSWORD=mysecretpassword psql -h localhost -U postgres - Verifica la configuración de autenticación de PostgreSQL: Si has personalizado
pg_hba.conf, comprueba que el método de autenticación permita la autenticación por contraseña
"Network not found"
- Asegúrate de que la red exista antes de iniciar los contenedores:
docker network create my-app-net - Si usas Docker Compose, the red se crea automáticamente al ejecutar
docker compose up