All deployment targets
Containers

Deploy to Docker Compose

The whole stack — API, Postgres, Redis, MinIO — on one machine.

From
Cost of the host
Ops effort
Medium
Managed Postgres
Persistent disk
Best for

Staging environments, on-premise installs, and anywhere you need the whole stack reproduced exactly as it runs locally.

Not for

Zero-downtime deploys. `compose up` stops the old container before the new one is ready.

Setup

  1. 1

    Use the production compose file

    Every Grit project ships `docker-compose.prod.yml` alongside the development one. It differs in the ways that matter: no bind mounts, no exposed database ports, restart policies on.

    docker compose -f docker-compose.prod.yml up -d --build
  2. 2

    Run migrations in the running container

    Grit does not auto-migrate on boot in production — a process that rewrites the schema every time it restarts is a bad idea when the platform can restart it for its own reasons. Run migrations as an explicit step.

    docker compose -f docker-compose.prod.yml exec api /app/migrate

What catches people out

The development compose file publishes Postgres on a host port so you can connect a GUI. The production one must not — that is how a database ends up on the public internet.

Named volumes survive `down`, but not `down -v`. That single flag is the difference between a restart and losing the database.

Platform dashboards and CLI flags change faster than these docs. For anything that looks different from what is written here, Docker Compose's own documentation is the authority: /docs/infrastructure/docker