Docker Compose Setup
This page covers running Phase Flag with Docker Compose for local development or a simple single-server deployment.
For a production-grade self-hosted deployment with SSL and nginx, see Self-Hosted (Production).
Prerequisites
- Docker 24+ with the Compose plugin
git(to clone the repository)- 2 GB RAM available for the stack
1. Clone the Repository
git clone https://github.com/phaseflag/phaseflag.git
cd phaseflag2. Configure Environment Variables
cp infra/docker/.env.example infra/docker/.envOpen infra/docker/.env and set the required values:
# Deployment mode — use "oss" for the open-source stack
PHASEFLAG_DEPLOYMENT_MODE=oss
# Database connection (the docker-compose service name is "postgres")
PHASEFLAG_DATABASE_URL=postgresql+asyncpg://phaseflag:phaseflag@postgres:5432/phaseflag
# Secrets — generate strong values for any non-local deployment
PHASEFLAG_JWT_SECRET_KEY=change-me-use-a-long-random-string
PHASEFLAG_API_SECRET_KEY=change-me-use-another-long-random-string
# CORS — comma-separated list of allowed origins
PHASEFLAG_CORS_ORIGINS=http://localhost:3000,http://localhost:5174
# Log level
PHASEFLAG_LOG_LEVEL=INFONever use the default secret values in production. Generate strong secrets with
openssl rand -hex 32.
3. Start the Stack
cd infra/docker
docker compose up -dThis starts three services:
| Service | Port | Description |
|---|---|---|
api | 8000 | FastAPI control plane |
dashboard | 3000 | React admin UI |
postgres | 5432 | PostgreSQL 16 database |
Verify all containers are running:
docker compose psExpected output:
NAME STATUS PORTS
phaseflag-api Up (healthy) 0.0.0.0:8000->8000/tcp
phaseflag-dashboard Up 0.0.0.0:3000->3000/tcp
phaseflag-postgres Up (healthy) 0.0.0.0:5432->5432/tcp4. Run Database Migrations
docker compose exec api alembic upgrade headYou should see Alembic applying all migrations:
INFO [alembic.runtime.migration] Running upgrade -> abc123, initial schema
INFO [alembic.runtime.migration] Running upgrade abc123 -> def456, add segments table
...5. Access the Dashboard
Open http://localhost:3000 in your browser.
Click Register and create your first user. On a fresh installation, the first user to register automatically receives the admin role.
From the dashboard you can:
- Create an organization and project
- Create feature flags
- Generate SDK API keys from Settings → API Keys
6. Verify the API
The interactive Swagger UI is available at:
http://localhost:8000/docsQuick health check:
curl http://localhost:8000/healthManaging the Stack
View logs
docker compose logs -f api
docker compose logs -f dashboardStop the stack
docker compose downStop and remove all data (full reset)
docker compose down -vPull the latest images
docker compose pull
docker compose up -dCreate a new Alembic migration (during development)
docker compose exec api alembic revision --autogenerate -m "add my table"Environment Variables Reference
| Variable | Required | Description |
|---|---|---|
PHASEFLAG_DEPLOYMENT_MODE | Yes | oss, saas, or enterprise |
PHASEFLAG_DATABASE_URL | Yes | PostgreSQL connection string |
PHASEFLAG_JWT_SECRET_KEY | Yes | Secret for signing JWT tokens |
PHASEFLAG_API_SECRET_KEY | Yes | Secret for API key HMAC signing |
PHASEFLAG_CORS_ORIGINS | Yes | Comma-separated allowed origins |
PHASEFLAG_LOG_LEVEL | No | DEBUG, INFO, WARNING, ERROR (default: INFO) |
PHASEFLAG_SMTP_HOST | No | SMTP host for password-reset emails |
PHASEFLAG_SMTP_PORT | No | SMTP port (default: 587) |
PHASEFLAG_FROM_EMAIL | No | Sender address for transactional email |
Troubleshooting
API container exits immediately
Check the logs:
docker compose logs apiCommon causes:
- Missing or malformed
PHASEFLAG_DATABASE_URL - PostgreSQL not yet ready when API starts — wait a few seconds and retry
Dashboard shows a blank screen
- Confirm the API is healthy:
curl http://localhost:8000/health - Check the browser console for CORS errors — ensure
PHASEFLAG_CORS_ORIGINSincludeshttp://localhost:3000
Database connection refused
# Wait for the postgres container to be healthy before running migrations
docker compose ps postgres
# Wait for "Up (healthy)" status, then:
docker compose exec api alembic upgrade head