Docker Compose es la forma más rápida de ejecutar una instancia de Sannvit Ledger, ya sea un entorno de desarrollo local o un despliegue de producción en un único host. Todo lo que sigue asume que ya ha clonado el repositorio.
La pila se divide en un fichero base más overrides que se van añadiendo según se necesiten:
| Servicio | Fichero de compose | Qué es |
|---|---|---|
db | docker-compose.yml | Un postgres:17 sin más — la única base de datos de la pila |
keycloak | docker-compose.keycloak.yml | Autenticación — Direct Access Grant, sin UI de login alojada |
api / alerting | docker-compose.api.yml | El servicio de ingesta, más su ejecutor independiente de integridad/alertas como un segundo contenedor |
dashboard | docker-compose.dashboard.yml | La interfaz de navegador |
rustfs | docker-compose.rustfs.yml | Almacén de blobs compatible con S3 incluido — opcional, vea Aporte su propio almacenamiento compatible con S3 |
mail | docker-compose.mail.yml | Capturador SMTP solo para desarrollo (Mailpit) para que los correos de invitación/restablecimiento/alerta lleguen a algún sitio visible |
nginx / caddy | docker-compose.nginx.yml / docker-compose.caddy.yml | Proxy inverso opcional con terminación TLS delante de los subdominios app. / api. / auth. |
La aplicación habla directamente con Postgres sin más, y Keycloak gestiona la autenticación — sin servicios adicionales en medio — lo que mantiene la huella lo bastante pequeña como para instalarla en la propia infraestructura de un cliente.
.env vive en la raíz del repositorio y lo lee cada fichero de compose.
cp .env.example .env
Como mínimo, rellene estos secretos antes de arrancar nada — openssl rand -hex 24 para cada uno:
POSTGRES_PASSWORDJWT_SECRETKEYCLOAK_ADMIN_PASSWORDKEYCLOAK_SERVICE_CLIENT_SECRETS3_ROOT_PASSWORD (solo necesario si usa el almacén de blobs incluido)EXPORT_SECRET_KEY (solo necesario antes de usar la función de exportación de paquetes de evidencia por SFTP)Para trabajo local, unos valores solo de desarrollo son suficientes — simplemente no los reutilice en ningún entorno real.
docker/run.sh gestiona qué ficheros de override de compose están activos y siempre lee .env desde la raíz del repositorio, sin importar el directorio de trabajo de su shell:
cd docker
./run.sh config add keycloak rustfs mail api api.dev dashboard dashboard.dev
./run.sh start
api.dev / dashboard.dev añaden recarga en caliente (código montado por bind mount, tsx watch / HMR de Nuxt) sobre sus servicios base.
npm run prod
que equivale a:
cd docker
COMPOSE_FILE=docker-compose.yml:docker-compose.keycloak.yml:docker-compose.rustfs.yml:docker-compose.api.yml:docker-compose.dashboard.yml \
COMPOSE_ENV_FILES=../.env COMPOSE_IGNORE_ORPHANS=true \
docker compose up -d --wait --build
!WARNING Antes de hacer esto en un entorno real:
- Los valores de
.env.exampleson marcadores de posición, no secretos — establezca valores reales y únicos para cada entrada listada arriba.- Ponga delante un proxy inverso real con terminación TLS (
docker-compose.nginx.ymlo.caddy.yml) en lugar de exponer los puertos de servicio en crudo, y establezcaPROXY_DOMAINen.env.- Cambie el secreto del cliente
ledger-servicede Keycloak respecto al valor de desarrollo por defecto de la exportación del realm (docker/volumes/keycloak/ledger-realm.json) desde la consola de administración de Keycloak, y actualiceKEYCLOAK_SERVICE_CLIENT_SECRETen.envpara que coincida.- Apunte
SMTP_*a un relay real en lugar de Mailpit, y establezcaDASHBOARD_URLal dominio público real del dashboard — vea Correo electrónico (SMTP) más abajo.- Configure procedimientos de copia de seguridad adecuados para el volumen de
db.
Este es un paso único por cada base de datos nueva — no forma parte de run.sh start. Espere a que db y keycloak reporten estar saludables (./run.sh status), y luego, desde la raíz del repositorio:
for f in api/drizzle/0*.sql; do
psql -h localhost -U postgres -d postgres -v ON_ERROR_STOP=1 -f "$f"
done
cd api
npm install
npm run db:functions # aplica src/db/functions/*.sql — no son objetos de drizzle-kit
npm run seed:demo # org de demo + equipo + clave de ingesta (la clave se imprime una vez, guárdela)
No hay un usuario de dashboard sembrado — seed:demo solo crea una org/equipo/clave de ingesta de demo para el lado del SDK. Para obtener un login humano, en su lugar arranque el primer administrador (desde api/, una vez que db y keycloak estén activos y las migraciones aplicadas):
npm run seed:admin -- you@example.com --org-name="Your Org Name"
Esto imprime una contraseña generada una sola vez. Cada usuario posterior se invita a través del dashboard (Organization → Users → Invite) por un compliance_admin ya existente, no mediante este script.
http://localhost:3000http://localhost:4010 (GET /healthz)http://localhost:8180http://localhost:8025http://localhost:9001 (RustFS incluido, si lo mantuvo)run.sh./run.sh logs [service] # seguir logs
./run.sh status # docker compose ps
./run.sh recreate [service] # forzar recreación de un servicio
./run.sh stop # detener todo
Invocar docker compose directamente en lugar de run.sh requiere especificar el fichero de entorno de forma explícita, por ejemplo desde la raíz del repositorio:
docker compose --env-file .env -f docker/docker-compose.yml -f docker/docker-compose.keycloak.yml up -d
Por defecto la pila incluye un contenedor RustFS como almacén de blobs para el contenido de los payloads — el propio ledger solo guarda un puntero + hash. Si prefiere apuntar a un bucket ya existente (AWS S3, Cloudflare R2, Backblaze B2, su propio MinIO/RustFS, etc.):
rustfs — omita ./run.sh config add rustfs, o ejecute ./run.sh config remove rustfs si ya estaba añadido..env, establezca S3_ENDPOINT, S3_PORT, S3_USE_SSL, y opcionalmente S3_REGION con los del proveedor externo, y S3_ACCESS_KEY / S3_SECRET_KEY con credenciales acotadas a ese bucket. Establezca LEDGER_BUCKET con el nombre del bucket.CreateBucket.El segundo plano de integridad append-only es un segundo bucket (LEDGER_INTEGRITY_BUCKET, por defecto ledger-integrity) en el mismo endpoint, creado con S3 Object Lock activado — imborrable durante su ventana de retención, incluso para administradores.
!CAUTION El contenedor RustFS incluido tiene errores abiertos en su implementación de Object Lock. Eso está bien para desarrollo, pero los despliegues de producción deberían apuntar
LEDGER_INTEGRITY_BUCKETa una implementación madura de Object Lock mediante la vía de traer su propio S3 — AWS S3 real, Backblaze B2, o GCS vía interoperabilidad con S3.
La API del ledger envía correos de invitación, restablecimiento de contraseña y resumen de alertas vía SMTP.
Desarrollo local — capture los correos en lugar de enviarlos:
./run.sh config add mail
./run.sh start
Cada correo llega a http://localhost:8025 (Mailpit) en lugar de a una bandeja de entrada real.
Producción — entregue correo real:
SMTP_ADMIN_EMAIL, SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, y SMTP_SENDER_NAME en el .env de ese entorno. Deje SMTP_ALLOW_INSECURE_AUTH sin definir — existe solo para Mailpit.DASHBOARD_URL con el dominio público real del dashboard — se incrusta en los enlaces de los correos de invitación/restablecimiento.mail en producción, o interceptará el correo real../run.sh recreate api alerting.Si su proveedor requiere verificación de dominio (SPF/DKIM, identidad del remitente — habitual con SES y Postmark), eso debe completarse en el lado del proveedor antes de que el correo llegue de verdad.
docker-compose.*.yml correspondiente si es necesario.docker compose pull.api / dashboard si su código fuente cambió: docker compose -f docker-compose.api.yml -f docker-compose.dashboard.yml up -d --build.Haga siempre una copia de seguridad de su base de datos antes de actualizar.
Para un despliegue en clúster más allá de un único host de Compose, existe una vía basada en Helm para Kubernetes — construcción/publicación de imágenes, secretos, DNS y helm install — cubierta por separado de Docker Compose.
Primeros pasos
Ponga en marcha su propia instancia de Sannvit Ledger, desde una copia limpia del repositorio hasta una cadena de auditoría funcionando.
Alojamiento en Kubernetes
Despliegue Sannvit Ledger en el clúster de Kubernetes de un cliente con el chart de Helm, para escalado horizontal más allá de un único host.