Compartir comentarios
Las respuestas se generan en base a la documentación.

Configuración inmediata y persistencia de datos

Esta guía te llevará de cero a un contenedor de PostgreSQL en funcionamiento en menos de cinco minutos, y luego te explicará cómo mantener tus datos seguros a través de los reinicios y eliminaciones de contenedores.

Descripción general

Ejecutar PostgreSQL en Docker requiere comprender un concepto crítico: los contenedores son efímeros, pero tus datos no deberían serlo. Esta guía cubre:

  • Iniciar PostgreSQL con un solo comando
  • Comprender por qué los contenedores pierden datos de forma predeterminada
  • Configurar volúmenes para almacenamiento persistente
  • Traducir tu configuración a Docker Compose

Inicio rápido (contenedor mínimo viable)

Note

Las imágenes endurecidas de Docker (DHI, Docker Hardened Images) son imágenes de aplicación y base de contenedor mínimas, seguras y listas para producción mantenidas por Docker. Se recomiendan las DHI siempre que sea posible para una mejor seguridad. Están diseñadas para reducir las vulnerabilidades y simplificar el cumplimiento, disponibles de forma gratuita para todos sin necesidad de suscripción, sin restricciones de uso y sin dependencia del proveedor (vendor lock-in).

Ejecuta PostgreSQL inmediatamente con este único comando:

Debes autenticarte en dhi.io antes de poder extraer imágenes endurecidas de Docker (DHI). Ejecuta docker login dhi.io para autenticarte.

docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -d dhi.io/postgres:18
$ docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -d postgres:18

Comprender las banderas (flags)

BanderaPropósito
--rmElimina automáticamente el contenedor cuando se detiene
--name postgres-devAsigna un nombre fácil de recordar en lugar de una cadena aleatoria
-e POSTGRES_PASSWORD=...Establece la contraseña del superusuario (requerido)
-p 5432:5432Mapea el puerto 5432 del host al puerto 5432 del contenedor
-dEjecuta el contenedor en segundo plano (modo desacoplado o detached)

Verifica que el contenedor se esté ejecutando:

$ docker ps --filter name=postgres-dev
CONTAINER ID   IMAGE         COMMAND                  STATUS         PORTS                    NAMES
a1b2c3d4e5f6   postgres:18   "docker-entrypoint.s…"   Up 2 seconds   0.0.0.0:5432->5432/tcp   postgres-dev

Conéctate usando psql desde el interior del contenedor:

$ docker exec -it postgres-dev psql -U postgres
psql (18.0)
Type "help" for help.

postgres=#

Ahora tienes una instancia de PostgreSQL en funcionamiento. Pero hay un problema: si detienes este contenedor, tus datos desaparecerán.

El problema de la persistencia de datos

Los contenedores utilizan un sistema de archivos efímero. Cuando se elimina un contenedor, todo lo que hay dentro de él, incluidos los archivos de tu base de datos, se elimina.

Demuéstralo tú mismo:

$ docker exec postgres-dev psql -U postgres -c "CREATE DATABASE testdb;"
CREATE DATABASE

$ docker exec postgres-dev psql -U postgres -c "\l" | grep testdb
 testdb    | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           |

$ docker stop postgres-dev
postgres-dev

$ docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -d dhi.io/postgres:18

$ docker exec postgres-dev psql -U postgres -c "\l" | grep testdb
(sin salida - la base de datos ha desaparecido)
$ docker exec postgres-dev psql -U postgres -c "CREATE DATABASE testdb;"
CREATE DATABASE

$ docker exec postgres-dev psql -U postgres -c "\l" | grep testdb
 testdb    | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           |

$ docker stop postgres-dev
postgres-dev

$ docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -d postgres:18

$ docker exec postgres-dev psql -U postgres -c "\l" | grep testdb
(sin salida - la base de datos ha desaparecido)

Tu base de datos testdb desapareció porque el nuevo contenedor comenzó con un sistema de archivos limpio. Este es el comportamiento esperado, y es exactamente por eso que existen los volúmenes.

Volúmenes con nombre

Los volúmenes con nombre son ubicaciones de almacenamiento gestionadas por Docker que persisten de forma independiente a los contenedores. Docker gestiona la ubicación en el sistema de archivos, los permisos y el ciclo de vida.

Crea un contenedor con un volumen con nombre:

Debes autenticarte en dhi.io antes de poder extraer imágenes endurecidas de Docker (DHI). Ejecuta docker login dhi.io para autenticarte.

$ docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -v postgres_data:/var/lib/postgresql \
  -d dhi.io/postgres:18
$ docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -v postgres_data:/var/lib/postgresql \
  -d postgres:18

La bandera -v postgres_data:/var/lib/postgresql monta un volumen con nombre llamado postgres_data en el directorio de datos de PostgreSQL. Si el volumen no existe, Docker lo crea automáticamente.

Note

PostgreSQL 18+ almacena los datos en un subdirectorio específico de la versión bajo /var/lib/postgresql. Montar a este nivel (en lugar de /var/lib/postgresql/data) facilita las actualizaciones posteriores utilizando pg_upgrade --link.

Verificar la persistencia de datos

Para verificar la persistencia de datos, repite la prueba anterior, pero esta vez con el volumen con nombre adjunto.

$ docker exec postgres-dev psql -U postgres -c "CREATE DATABASE testdb;"
CREATE DATABASE

$ docker stop postgres-dev
postgres-dev

$ docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -v postgres_data:/var/lib/postgresql \
  -d dhi.io/postgres:18

$ docker exec postgres-dev psql -U postgres -c "\l" | grep testdb
 testdb    | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           |
$ docker exec postgres-dev psql -U postgres -c "CREATE DATABASE testdb;"
CREATE DATABASE

$ docker stop postgres-dev
postgres-dev

$ docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -v postgres_data:/var/lib/postgresql \
  -d postgres:18

$ docker exec postgres-dev psql -U postgres -c "\l" | grep testdb
 testdb    | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           |

Si ves testdb en la salida, la persistencia funciona: la base de datos sobrevivió porque el volumen preservó el directorio de datos.

Gestionar volúmenes

Listar todos los volúmenes:

$ docker volume ls --filter name=postgres_data
DRIVER    VOLUME NAME
local     postgres_data

Inspecciona un volumen para ver sus detalles:

$ docker volume inspect postgres_data
[
    {
        "CreatedAt": "2025-01-05T10:30:00Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/postgres_data/_data",
        "Name": "postgres_data",
        "Options": null,
        "Scope": "local"
    }
]

Elimina un volumen no utilizado (advertencia: esto elimina todos los datos):

$ docker volume rm postgres_data

Montajes de tipo bind (alternativa)

Los montajes de tipo bind (bind mounts) mapean un directorio específico del host a una ruta del contenedor. A diferencia de los volúmenes con nombre, controlas exactamente dónde residen los datos en el sistema de archivos del host.

Crea un directorio en tu máquina host para almacenar los datos de Postgres.

mkdir -p ~/postgres-data && sudo chown -R 999:999 ~/postgres-data

Ejecuta Postgres usando un montaje bind.

docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -v ~/postgres-data:/var/lib/postgresql \
  -d dhi.io/postgres:18
$ mkdir -p ~/postgres-data

Ejecuta Postgres usando un montaje bind.

$ docker run --rm --name postgres-dev \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -v ~/postgres-data:/var/lib/postgresql \
  -d postgres:18

Cuándo usar montajes bind

Los montajes bind son útiles cuando necesitas acceso directo del sistema de archivos al directorio de datos para scripts de respaldo que leen archivos directamente, al integrarse con herramientas de monitoreo a nivel de host, o cuando existen requisitos de permisos específicos. Para la mayoría de los escenarios de desarrollo y producción, los volúmenes con nombre son más simples y menos propensos a errores.

Problemas comunes de los montajes bind

Los errores de permisos son el problema más frecuente con los montajes bind. PostgreSQL se ejecuta como el usuario postgres (UID 999) dentro del contenedor. Si el directorio de tu host tiene permisos restrictivos, el contenedor no se iniciará.

Verifica los registros (logs) si el contenedor se cierra inmediatamente:

$ docker logs postgres-dev

Configuración de Docker Compose

Docker Compose captura toda tu configuración en un archivo, lo que hace que las configuraciones sean reproducibles y más fáciles de gestionar a medida que crece la complejidad.

Crea un archivo compose.yaml:

services:
  db:
    image: postgres:18
    container_name: postgres-dev
    environment:
      POSTGRES_PASSWORD: mysecretpassword
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql

volumes:
  postgres_data:

Inicia la base de datos:

$ docker compose up -d

Detén y elimina los contenedores (el volumen persiste):

$ docker compose down

Alternativamente, puedes detener, eliminar los contenedores y borrar el volumen:

$ docker compose down -v

Este archivo de Compose se convierte en la base para agregar scripts de inicialización, ajuste de rendimiento y servicios complementarios cubiertos en las guías siguientes.

Referencia de variables de entorno

La imagen oficial de PostgreSQL admite estas variables de entorno:

VariableRequeridaDescripción
POSTGRES_PASSWORDContraseña del superusuario
POSTGRES_USERNoNombre del superusuario (predeterminado: postgres)
POSTGRES_DBNoNombre de la base de datos predeterminada (predeterminado: el valor de POSTGRES_USER)

Pasos siguientes

Con el almacenamiento persistente configurado, estás listo para personalizar aún más PostgreSQL. El siguiente capítulo de la guía cubre:

  • Creación automatizada de esquemas con scripts de inicialización
  • Ajuste de rendimiento para cargas de trabajo contenedorizadas
  • Configuración de zona horaria e idioma (locale)