Docker
One container, its own database, nothing else to run — and what changes when you publish it somewhere real.
The smallest shared deployment is one container and one volume.
docker run -p 3001:3001 -v datagripe:/data ghcr.io/datagripe/datagripe
Zero-config DataGripe: it starts its own PostgreSQL under /data,
migrates it, generates its own secrets, and runs with no accounts. Open
http://localhost:3001.
The volume is not optional
Without -v, a restart loses two things: the database, and the generated
key the datasource passwords in it were encrypted with. The second is the
one that hurts, because it is not recoverable — see
configuration.
Anything under /data is state. Back it up as a unit, or run an external
PostgreSQL and back that up instead.
Any other port means saying so
WEB_ORIGIN is the exact origin browsers use, and both the HTTP routes
and the WebSocket upgrade compare against it. Publishing on a different
port without setting it is the single most common broken deployment: the
page loads, and then nothing in it works, because the socket everything
runs over was refused.
docker run -p 8080:3001 -e WEB_ORIGIN=http://localhost:8080 \ -v datagripe:/data ghcr.io/datagripe/datagripe
The same applies behind a proxy or a hostname:
docker run -p 3001:3001 -e WEB_ORIGIN=https://datagripe.example.com \ -e NODE_ENV=production -v datagripe:/data ghcr.io/datagripe/datagripe
NODE_ENV=production adds Secure to the session cookie. That is
correct behind TLS and wrong in front of plain HTTP, where the
browser will not send the cookie back and sign-in will not stick.
Turning accounts on
The zero-config shape has no accounts, which is right for one person and wrong for a team. Accounts come on when you give it a database of its own:
docker run -p 3001:3001 \ -e APP_DATABASE_URL=postgres://user:password@db:5432/datagripe \ -e CONNECTION_ENCRYPTION_KEY="$(openssl rand -base64 32)" \ -e SESSION_SECRET="$(openssl rand -base64 32)" \ -e WEB_ORIGIN=https://datagripe.example.com \ -e NODE_ENV=production \ ghcr.io/datagripe/datagripe
Setting APP_DATABASE_URL selects external mode, which turns accounts on
and stops the server migrating itself. The first person to open it
creates the first account; after that signup is closed unless
ALLOW_SIGNUP=true.
Generate those two secrets once and keep them. Regenerating
SESSION_SECRET only signs everyone out; regenerating
CONNECTION_ENCRYPTION_KEY orphans every stored datasource password.
Migrations
The app applies pending migrations at startup in every deployment, before serving requests. The image also has a migration-only entry point for operators who want to apply changes before rollout:
docker run --rm \ -e APP_DATABASE_URL=… -e CONNECTION_ENCRYPTION_KEY=… -e SESSION_SECRET=… \ ghcr.io/datagripe/datagripe migrate
Running it separately is optional. Applied files are skipped, and concurrent runners are serialized by a database advisory lock. Compose runs this as a one-shot service, Helm as a pre-install hook, and the plain manifests as an init container — see upgrading.
Images and tags
The image is ghcr.io/datagripe/datagripe. A version tag is a specific
release and is what a deployment should pin; latest follows the newest
one, which is fine for trying it and not for a service other people
depend on.
Related
- Compose — the same thing with a PostgreSQL beside it.
- Kubernetes — Helm and plain manifests.
- Configuration — every variable, a page per decision.
- Security — what to switch off before it faces anyone.
This page as Markdown, for an agent or a diff.