Docker Services¶
Carbon Connect uses Docker Compose to run its three core infrastructure services locally: PostgreSQL (with pgvector), Valkey (Redis-compatible cache), and Meilisearch (full-text search). An optional dev profile adds database and cache management UIs.
Architecture Overview¶
graph LR
subgraph Docker Compose
PG["PostgreSQL 16<br/>+ pgvector<br/>:5433"]
VK["Valkey 8<br/>(Redis-compatible)<br/>:6379"]
MS["Meilisearch 1.6<br/>:7700"]
end
subgraph Dev Profile
AD["Adminer<br/>(DB UI)<br/>:8080"]
VC["Valkey Commander<br/>(Cache UI)<br/>:8081"]
end
API["FastAPI<br/>:8000"] --> PG
API --> VK
API --> MS
AD --> PG
VC --> VK Services¶
PostgreSQL 16 with pgvector¶
The primary relational database extended with pgvector for 768-dimensional vector similarity search.
| Property | Value |
|---|---|
| Image | pgvector/pgvector:pg16 |
| Container Name | granted_carbon_postgres |
| External Port | 5433 (mapped from internal 5432) |
| Database | grant_engine |
| Username | grant_user |
| Password | grant_password_dev |
| Volume | granted_carbon_postgres_data |
Port 5433
The external port is 5433, not the default 5432. This avoids conflicts with local PostgreSQL installations on Windows.
Health Check: Runs pg_isready every 10 seconds with 5 retries.
Init Script: The file scripts/init-extensions.sql is mounted to /docker-entrypoint-initdb.d/ and runs on first container creation. It creates the pgvector extension required for embedding storage and similarity search.
Connection Strings:
Valkey 8¶
Redis-compatible in-memory data store used for caching, session storage, and as the Celery message broker and result backend. Valkey is 100% compatible with Redis clients and is approximately 20% cheaper on AWS (ElastiCache).
| Property | Value |
|---|---|
| Image | valkey/valkey:8-alpine |
| Container Name | granted_carbon_valkey |
| Port | 6379 |
| Volume | granted_carbon_valkey_data |
| Persistence | Append-only file (--appendonly yes) |
Health Check: Runs valkey-cli ping every 10 seconds with 5 retries.
Connection URL: redis://localhost:6379/0
Redis Protocol Compatibility
Despite being Valkey, the connection URL uses the redis:// protocol scheme. All Redis client libraries (including Python redis and Celery) work without modification.
Meilisearch 1.6¶
High-performance full-text search engine providing sub-100ms search latency across 100k+ grant documents.
| Property | Value |
|---|---|
| Image | getmeili/meilisearch:v1.6 |
| Container Name | granted_carbon_meilisearch |
| Port | 7700 |
| Volume | granted_carbon_meilisearch_data |
| Master Key | meilisearch_dev_master_key_change_in_prod (configurable via MEILI_MASTER_KEY) |
| Analytics | Disabled (MEILI_NO_ANALYTICS=true) |
Health Check: Runs curl -f http://localhost:7700/health every 10 seconds with 5 retries.
Environment Variables (container-level):
| Variable | Value | Description |
|---|---|---|
MEILI_MASTER_KEY | ${MEILI_MASTER_KEY:-...} | API authentication key (reads from .env) |
MEILI_ENV | development | Runtime environment |
MEILI_NO_ANALYTICS | true | Disables telemetry |
Dev Profile Services¶
These services are only started when using the dev profile. They provide web-based management interfaces for development convenience.
Adminer (Database UI)¶
| Property | Value |
|---|---|
| Image | adminer:latest |
| Container Name | granted_carbon_adminer |
| Port | 8080 |
| Depends On | postgres |
Access at http://localhost:8080 and connect with:
- System: PostgreSQL
- Server:
postgres(Docker service name) - Username:
grant_user - Password:
grant_password_dev - Database:
grant_engine
Valkey Commander (Cache UI)¶
| Property | Value |
|---|---|
| Image | rediscommander/redis-commander:latest |
| Container Name | granted_carbon_valkey_commander |
| Port | 8081 |
| Depends On | valkey |
| Redis Host | local:valkey:6379 |
Access at http://localhost:8081 to browse keys, monitor connections, and inspect Celery queues.
Commands¶
Starting Services¶
# Start core services (PostgreSQL, Valkey, Meilisearch)
docker compose up -d
# Start with dev tools (adds Adminer and Valkey Commander)
docker compose --profile dev up -d
# Start a specific service
docker compose up -d postgres
Stopping Services¶
# Stop all running containers (preserves data)
docker compose down
# Stop and remove all volumes (fresh start, destroys data)
docker compose down -v
# Stop only dev profile services
docker compose --profile dev down
Monitoring¶
# View running containers and their health status
docker compose ps
# Follow logs for all services
docker compose logs -f
# Follow logs for a specific service
docker compose logs -f postgres
docker compose logs -f valkey
docker compose logs -f meilisearch
Direct Container Access¶
# Open PostgreSQL interactive shell
docker exec -it granted_carbon_postgres psql -U grant_user -d grant_engine
# List database tables
docker exec granted_carbon_postgres psql -U grant_user -d grant_engine -c "\dt"
# Check pgvector extension
docker exec granted_carbon_postgres psql -U grant_user -d grant_engine -c "SELECT * FROM pg_extension WHERE extname = 'vector';"
# Ping Valkey
docker exec granted_carbon_valkey valkey-cli ping
# List Valkey keys
docker exec granted_carbon_valkey valkey-cli keys "*"
# Check Meilisearch health
curl http://localhost:7700/health
# List Meilisearch indexes
curl http://localhost:7700/indexes -H "Authorization: Bearer meilisearch_dev_master_key_change_in_prod"
Volumes¶
Docker Compose defines three named volumes for data persistence across container restarts:
| Volume Name | Service | Mount Point |
|---|---|---|
granted_carbon_postgres_data | PostgreSQL | /var/lib/postgresql/data |
granted_carbon_valkey_data | Valkey | /data |
granted_carbon_meilisearch_data | Meilisearch | /meili_data |
Volume Cleanup
Running docker compose down -v deletes all named volumes and their data. This is useful for a fresh start but will destroy your local database, cache, and search indexes. You will need to re-run Alembic migrations (poetry run alembic upgrade head) after volume deletion.
Network¶
All services share a single Docker network:
| Property | Value |
|---|---|
| Network Name | granted_carbon_network |
| Driver | bridge (default) |
Services can reference each other by their Docker Compose service names (postgres, valkey, meilisearch) within the network. External access from the host uses localhost with the mapped ports.
Troubleshooting¶
Docker containers fail to start
- Ensure Docker Desktop is running and has sufficient resources allocated.
- Check for port conflicts:
- If ports are occupied, stop the conflicting service or change the port mapping in
docker-compose.yml. - Remove stale containers and volumes:
PostgreSQL health check failing
The health check runs pg_isready which requires the PostgreSQL process to be fully initialized. On first startup with a fresh volume, initialization may take 15-30 seconds. Check the logs:
Meilisearch returns 403 Forbidden
Verify you are passing the correct master key in the Authorization header:
curl http://localhost:7700/indexes \
-H "Authorization: Bearer meilisearch_dev_master_key_change_in_prod"
MEILI_MASTER_KEY in .env, the container must be recreated: Valkey connection refused
Verify the container is running and healthy:
Expected response:PONG Out of disk space
Docker volumes can accumulate data over time. To reclaim space:
Docker Compose File Reference¶
The full docker-compose.yml is located at the project root. Key structural notes:
- Compose version: 3.9
- Restart policy: All services use
unless-stopped - Health checks: All three core services define health checks with 10-second intervals and 5 retries
- Init script: PostgreSQL mounts
scripts/init-extensions.sqlas a read-only init script - Dev profile: Adminer and Valkey Commander are gated behind the
devprofile to keep the default startup lightweight