Configuración avanzada e inicialización
Con el almacenamiento persistente configurado en la sección anterior, estás listo para personalizar PostgreSQL para su uso en el mundo real. Esta guía cubre técnicas de configuración avanzada para ejecutar PostgreSQL en contenedores de Docker, incluyendo la inicialización automatizada de bases de datos, el ajuste de rendimiento y la configuración de la zona horaria.
Descripción general
Aunque los contenedores de PostgreSQL se pueden iniciar rápidamente con la configuración predeterminada, los entornos de producción requieren configuraciones personalizadas. Esta guía explica cómo:
- Automatizar la creación de bases de datos, esquemas y usuarios durante el inicio del contenedor
- Ajustar los parámetros de rendimiento de PostgreSQL para cargas de trabajo contenedorizadas
- Configurar la zona horaria y el idioma (locale)
Scripts de inicialización
La imagen oficial de Docker para PostgreSQL admite la ejecución automática de scripts de inicialización cuando el contenedor se inicia por primera vez. Cualquier archivo colocado en el directorio /docker-entrypoint-initdb.d/ se ejecuta en orden alfabético.
Cómo funciona la inicialización
Cuando el contenedor se inicia, verifica si el directorio de datos de PostgreSQL está vacío. Si el directorio ya contiene datos, PostgreSQL se inicia inmediatamente sin realizar ninguna inicialización. Si el directorio está vacío, el contenedor ejecuta initdb para crear un nuevo clúster de base de datos, luego ejecuta todos los scripts en /docker-entrypoint-initdb.d/ en orden alfabético antes de iniciar PostgreSQL.
Formatos de archivo compatibles
| Formato | Descripción |
|---|---|
.sql | Comandos SQL ejecutados directamente |
.sql.gz | Archivos SQL comprimidos con Gzip |
.sh | Scripts de shell ejecutados con bash |
ImportantLos scripts de inicialización solo se ejecutan cuando el directorio de datos de PostgreSQL (
/var/lib/postgresql/data) está vacío. Si montas un volumen que contiene datos existentes, se omitirá la inicialización. Este comportamiento evita que se sobrescriban las bases de datos existentes.
Montar scripts de inicialización
Usa Docker Compose para montar scripts de inicialización en el contenedor. Primero, crea un directorio de proyecto:
$ mkdir -p postgres-project/init-db
$ cd postgres-project
Crea un archivo compose.yaml:
services:
db:
image: postgres:18
volumes:
- ./init-db:/docker-entrypoint-initdb.d
- postgres_data:/var/lib/postgresql
environment:
POSTGRES_PASSWORD: mysecretpassword
volumes:
postgres_data:Todos los scripts en el directorio ./init-db se ejecutan cuando el contenedor se inicia por primera vez. Esto es ideal para inicializar bases de datos.
Ejemplo de script de inicialización
Crea un archivo llamado init.sql en tu directorio init-db:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);Este script se ejecuta automáticamente cuando el contenedor se inicia por primera vez, creando tu esquema de base de datos inicial.
NoteAsegúrate de que los scripts de inicialización tengan los permisos de lectura adecuados. Si te encuentras con errores de "Permiso denegado", ejecuta
chmod 644 init-db/*.sqlpara que los archivos sean legibles por el contenedor.
Ajuste de rendimiento
La configuración predeterminada de PostgreSQL es conservadora para funcionar en sistemas con recursos limitados. Para cargas de trabajo de producción, debes ajustar estos parámetros según los recursos asignados a tu contenedor.
Método 1: Archivo de configuración personalizado
Para obtener un control total, monta un archivo postgresql.conf personalizado. Primero, extrae la configuración predeterminada:
$ docker run -i --rm postgres:18 cat /usr/share/postgresql/postgresql.conf.sample > my-postgres.conf
Edita my-postgres.conf con la configuración deseada, luego móntalo en tu archivo de Compose:
services:
db:
image: postgres:18
volumes:
- ./my-postgres.conf:/etc/postgresql/postgresql.conf
- ./init-db:/docker-entrypoint-initdb.d
- postgres_data:/var/lib/postgresql
command: postgres -c config_file=/etc/postgresql/postgresql.conf
environment:
POSTGRES_PASSWORD: mysecretpassword
volumes:
postgres_data:Parámetros clave de configuración
Las siguientes tablas enumeran parámetros importantes de postgresql.conf para despliegues contenedorizados de PostgreSQL.
Configuración de conexión
| Parámetro | Descripción | Valor predeterminado |
|---|---|---|
listen_addresses | Direcciones IP en las que escuchar | localhost |
port | Número de puerto TCP | 5432 |
max_connections | Máximo de conexiones concurrentes | 100 |
Configuración de memoria
| Parámetro | Descripción | Valor inicial recomendado |
|---|---|---|
shared_buffers | Memoria compartida para caché | 25% de la memoria del contenedor |
work_mem | Memoria por operación de consulta | 4MB - 64MB |
maintenance_work_mem | Memoria para VACUUM, CREATE INDEX | 64MB - 256MB |
effective_cache_size | Estimación del tamaño de caché del planificador | 50-75% de la memoria del contenedor |
Límites de memoria de Docker
Al ajustar los parámetros de memoria, establece límites de memoria explícitos en tu contenedor utilizando deploy.resources.limits.memory en Compose o --memory con docker run. Sin límites, PostgreSQL ve la RAM total del host y podría asignar más de lo previsto. Por ejemplo, si tu contenedor debe usar un máximo de 4 GB, establece shared_buffers en aproximadamente 1 GB (25%).
Configuración de E/S
| Parámetro | Descripción | Valor inicial recomendado |
|---|---|---|
effective_io_concurrency | Operaciones de E/S de disco concurrentes | 200 para SSD, 2 para HDD |
Configuración de límites de tiempo (timeout)
| Parámetro | Descripción | Valor predeterminado |
|---|---|---|
statement_timeout | Tiempo máximo para cualquier sentencia | 0 (desactivado) |
lock_timeout | Tiempo máximo de espera para un bloqueo | 0 (desactivado) |
deadlock_timeout | Tiempo antes de verificar un interbloqueo (deadlock) | 1s |
transaction_timeout | Tiempo máximo para una transacción | 0 (desactivado) |
NoteEstablecer
shared_buffersdemasiado alto en un contenedor puede exceder los límites de memoria compartida del kernel. No uses más del 25-30% del límite de memoria del contenedor.
Configuración de zona horaria e idioma (locale)
Una localización adecuada garantiza que las marcas de tiempo y el ordenamiento se comporten correctamente para los usuarios de tu aplicación.
services:
db:
image: postgres:18
volumes:
- postgres_data:/var/lib/postgresql
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
environment:
POSTGRES_PASSWORD: mysecretpassword
TZ: America/New_York
volumes:
postgres_data:Alternativamente, establece la zona horaria usando un parámetro de línea de comandos de PostgreSQL:
services:
db:
image: postgres:18
command: ["postgres", "-c", "timezone=America/New_York"]
environment:
POSTGRES_PASSWORD: mysecretpasswordConfigurar el idioma (locale)
Especifica la configuración de idioma (locale) durante la inicialización de la base de datos usando la variable de entorno POSTGRES_INITDB_ARGS:
services:
db:
image: postgres:18
volumes:
- postgres_data:/var/lib/postgresql
environment:
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --lc-collate=en_US.UTF-8 --lc-ctype=en_US.UTF-8"
volumes:
postgres_data:Esto afecta a la colación (ordenamiento) y al comportamiento de procesamiento de caracteres. Cambiar esta variable después de la creación de la base de datos no tiene ningún efecto: solo se aplica durante la primera ejecución cuando se inicializa el directorio de datos.
Conectarse a la base de datos
Puedes interactuar con PostgreSQL ejecutándose en un contenedor incluso sin tener psql instalado en tu máquina host.
Shell interactivo
Abre una sesión de psql dentro del contenedor:
$ docker exec -it postgres-container psql -U postgres
Conéctate a una base de datos específica:
$ docker exec -it postgres-container psql -U postgres -d mydb