Ir al contenido

Primeros pasos con Docker Compose

El repositorio incluye un stack Compose bajo deploy/compose/: un despliegue endurecido de nodo único (SQLite embebido, cero dependencias externas) más dos overlays — un override multi-tenant con Postgres y un perfil de copia de seguridad para recuperación ante desastres. Este tutorial te lleva desde up -d hasta un control plane configurado con copias de seguridad.

El contenedor envuelve el mismo binario único que cualquier otra instalación; solo difiere el empaquetado. Los comandos de abajo son los propios puntos de entrada documentados del stack (deploy/compose/*.yml), y el flujo de primer arranque que conducen es el mismo que se verifica de extremo a extremo contra el binario en el tutorial de nodo único.

  1. Arráncalo:

    En hosts donde AppArmor controla la creación de espacios de nombres de usuario, completa “Session confinement on AppArmor hosts” en deploy/compose/README.md en el host del daemon de Docker antes de iniciar la pila.

    Ventana de terminal
    docker compose -f deploy/compose/docker-compose.yml up --wait --wait-timeout 120

    Lo que obtienes, por diseño:

    Propiedad Valor
    Puertos 8443 (HTTPS: REST + UI web), 8444 (gRPC) — publicados en todas las interfaces del host, porque esto es un servidor. Pon OLIVARES_BIND=127.0.0.1 en .env para restringirlos al host
    Datos volumen nombrado olivares-data → /var/lib/olivares (almacén SQLite, clave de firma de auditoría, material TLS)
    Endurecimiento corre como 65532:65532, root de solo lectura, todas las capabilities descartadas, no-new-privileges, tmpfs /tmp
    Healthcheck ejecución directa de olivares readyz dentro del binario — sin shell, curl ni wget. Sólo un HTTP 200 de /readyz local es saludable
  2. Pregunta al motor dónde está, y lee el token de configuración de un solo uso de los logs:

    Ventana de terminal
    # where the console answers, and whether setup is still pending. It runs the binary
    # directly and needs no shell.
    docker compose -f deploy/compose/docker-compose.yml exec olivares olivares first-boot
    # the one-time setup token, printed once at first boot
    docker compose -f deploy/compose/docker-compose.yml logs olivares \
    | sed -n '/FIRST-BOOT SETUP/,/========================/p'
  3. Crea el primer administrador, inicia sesión, y crea tu organización — exactamente como en el tutorial de nodo único (la API es la misma; el certificado TLS es autofirmado en el primer arranque, así que curl -k para el bootstrap):

    Ventana de terminal
    curl -ksf -X POST https://localhost:8443/v1/setup \
    -H 'Content-Type: application/json' \
    -d '{"token":"<olst_ token>","email":"you@example.com","password":"<strong-password>"}'

Las fuentes se declaran en un único fichero de operador nombrado por OLIVARES_SOURCES_CONFIG (conectar una fuente). Para el contenedor, monta el fichero y establece la variable con un pequeño override:

# deploy/compose/docker-compose.sources.yml (yours — not shipped)
services:
olivares:
environment:
OLIVARES_SOURCES_CONFIG: /etc/olivares/sources.json
volumes:
- ./sources.json:/etc/olivares/sources.json:ro
Ventana de terminal
docker compose -f deploy/compose/docker-compose.yml \
-f deploy/compose/docker-compose.sources.yml up -d
docker compose -f deploy/compose/docker-compose.yml logs olivares | grep "ingest: wired source"

Recuerda que las rutas dentro de sources.json son rutas de contenedor — un tail de log pgAudit, por ejemplo, necesita que el directorio de logs de Postgres también esté montado de solo lectura dentro del contenedor.

3. Copias de seguridad DR cifradas (el perfil backup)

Sección titulada «3. Copias de seguridad DR cifradas (el perfil backup)»

El stack incluye un servicio de copia de seguridad de un solo disparo que produce un bundle cifrado y con continuidad de ledger segura (olivares dr backup):

Guarda la passphrase en un archivo privado fuera del repositorio y de la imagen, y conserva una copia en un lugar seguro fuera de este host: sin ella no se puede restaurar ningún bundle. Dale al contenedor de backup acceso de solo lectura (la imagen se ejecuta con el UID 65532):

Ventana de terminal
sudo install -d -o 65532 -g 65532 -m 0700 /srv/olivares-dr
sudo install -o 65532 -g 65532 -m 0400 /path/to/private-passphrase /srv/olivares-dr/dr-pass
BACKUP_TS="$(date -u +%Y%m%dT%H%M%SZ)" \
docker compose -f deploy/compose/docker-compose.yml \
-f deploy/compose/docker-compose.backup.yml \
-f - --profile backup run --rm backup <<'YAML'
services:
backup:
volumes:
- /srv/olivares-dr/dr-pass:/run/secrets/dr-pass:ro
YAML

Envuelve ese comando en el cron del host para un RPO programado, y espeja el volumen olivares-backups offsite — una copia de seguridad en el mismo host no es recuperación ante desastres, y la passphrase debe viajar por separado de los bundles (3-2-1). El procedimiento completo, incluyendo el simulacro de restauración (olivares dr verify), está en copia de seguridad y restauración.

4. Opcional: el override multi-tenant con Postgres

Sección titulada «4. Opcional: el override multi-tenant con Postgres»

Para la topología multi-tenant, superpón el override de Postgres. Levanta un Postgres 16, aprovisiona el rol de mínimo privilegio olivares_app (sin superuser, sin BYPASSRLS — el motor se niega a arrancar contra un rol privilegiado, porque la seguridad a nivel de fila es el backstop del tenant), y apunta el motor a él:

El override también aprovisiona olivares_admin, un rol separado con NOSUPERUSER BYPASSRLS y acceso de solo lectura a las tablas del motor. El motor lo usa mediante --admin-dsn para lecturas entre tenants, incluida la configuración inicial.

Fija primero tres contraseñas distintas, usando solo A-Z a-z 0-9 . _ ~ - para esta demo de Compose, y luego levanta el stack:

Ventana de terminal
cp deploy/compose/.env.example deploy/compose/.env
# set three distinct passwords in deploy/compose/.env:
# POSTGRES_SUPERUSER_PASSWORD, OLIVARES_DB_PASSWORD, OLIVARES_ADMIN_PASSWORD
docker compose -f deploy/compose/docker-compose.yml \
-f deploy/compose/docker-compose.postgres.yml up -d
Ventana de terminal
curl -ks https://localhost:8443/readyz
# {"leader":true,"setup_required":false,"status":"ok","store":"up"}
curl -ks https://localhost:8443/metrics | grep olivares_store_up