Skip to content

Add a migration init container to compose.yml for seamless quickstart setup #57

@Dhruwang

Description

@Dhruwang

Problem

The current quickstart workflow requires users to run database migrations manually using goose, which introduces several friction points:

  1. Go or goose must be installed locally — the docs suggest go install github.com/pressly/goose/v3/cmd/goose@v3.26.0, but Go isn't listed as a prerequisite (#55)
  2. Migration files aren't available — the quickstart only provides compose.yml, but the migrations/ directory lives in the full repo and is never downloaded (#56)
  3. River queue tables also need migrating — even if app migrations run, the API crash-loops because river_leader and river_queue tables don't exist. This requires a separate river migrate-up command that isn't documented in the quickstart
  4. make init-db is referenced but no Makefile is provided in the quickstart flow (#54)

The net result: docker compose up alone does not produce a working system. The API fails with vector type not found or relation "river_queue" does not exist errors.

Proposed solution

Add a one-shot migration init container to compose.yml that runs before the Hub API starts. The ghcr.io/formbricks/hub:latest image already bundles goose, river, and the migration SQL files, so no additional tooling or files are needed on the host.

hub-migrate:
  image: ghcr.io/formbricks/hub:latest
  restart: "no"
  entrypoint: ["sh", "-c"]
  command:
    [
      'if [ -x /usr/local/bin/goose ] && [ -x /usr/local/bin/river ]; then /usr/local/bin/goose -dir /app/migrations postgres "$$DATABASE_URL" up && /usr/local/bin/river migrate-up --database-url "$$DATABASE_URL"; else echo ''Migration tools (goose/river) not in image.''; exit 1; fi',
    ]
  environment:
    DATABASE_URL: postgresql://formbricks:${POSTGRES_PASSWORD:-formbricks_dev}@postgres:5432/hub?sslmode=disable
  depends_on:
    postgres:
      condition: service_healthy
  networks:
    - formbricks_hub

The hub service then depends on it:

hub:
  depends_on:
    postgres:
      condition: service_healthy
    hub-migrate:
      condition: service_completed_successfully

Why this approach over a Makefile

Migration container Makefile
Extra host dependencies None Go (or standalone goose)
Migration files needed locally No (bundled in image) Yes (must clone repo)
Setup command docker compose up -d make init-db && docker compose up -d
Target audience fit Quickstart / Docker users Developers working on the Go codebase

For the quickstart audience (deploying via Docker), a single docker compose up -d that handles everything is the ideal experience. The Makefile remains useful for local development but shouldn't be a prerequisite for Docker-based deployment.

Additional note

$DATABASE_URL in the command must be escaped as $$DATABASE_URL — otherwise Docker Compose interpolates it with the host's value (typically empty) instead of letting the container's shell resolve it at runtime.

Verified

This approach was tested end-to-end. All 6 app migrations and 6 River queue migrations apply successfully, and the Hub API starts cleanly with a healthy /health endpoint.

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions