Docker Workflow Guide
This guide explains our Docker workflow for local development and how production deployments work.
Overview
- Local Development:
docker-compose.local.yml
with Supabase CLI - Production: Individual containers managed by
deploy-unraid.yml
GitHub Actions workflow
Local Development Workflow
Prerequisites
- Docker Desktop installed and running
- Supabase CLI installed (
brew install supabase/tap/supabase
) - Git
Quick Start
# 1. Clone and navigate to the project
git clone https://github.com/eddie-rowe/vertical-farm.git
cd vertical-farm
# 2. Start the local development environment
make up
# or
./scripts/setup-local-dev.sh
This script will:
1. Check prerequisites (Docker, Supabase CLI)
2. Start Supabase services locally
3. Create .env.local
with auto-populated Supabase keys
4. Start application containers with hot-reloading
Access Points
- Frontend: http://localhost:3000
- Backend API: http://localhost:8000
- API Docs: http://localhost:8000/docs
- Supabase Studio: http://localhost:54323
Key Features of Local Setup
- Hot Reloading: Code changes are reflected immediately
- Volume Mounts: Your local code is mounted into containers
- Supabase CLI: Full local Supabase instance (no cloud costs)
- Optional Datadog: Use
--profile monitoring
to include Datadog agent
Common Local Commands
# View logs
make logs # All services
make logs-service # Specific service (interactive)
# Stop everything
make down # Stops containers and asks about Supabase
make down-docker # Stops only Docker containers
# Reset database
supabase db reset # Wipes and re-applies migrations
# Clean up
make clean-docker # Removes containers and volumes
Production Deployment Workflow
unRAID Deployment via GitHub Actions
Production uses a sophisticated unRAID deployment strategy with individual container management:
- Trigger: Merge to
main
or manual workflow dispatch - Build Phase:
- Backend and Frontend images built separately
- Images pushed to GitHub Container Registry (GHCR)
- Deploy Phase (via self-hosted runner on unRAID):
- Pulls new images from GHCR
- Stops existing containers
- Deploys new containers with
docker run
- Each service managed individually for zero-downtime updates
How It Works
The deploy-unraid.yml
workflow:
- Runs on a self-hosted runner directly on your unRAID server
- Creates a shared Docker network (vertical-farm-network
)
- Deploys each container individually:
- Backend: Port 8000
- Frontend: Port 3000
- Datadog Agent: Port 8126
Key Benefits
- unRAID Native: Works perfectly with unRAID's container management UI
- Zero Downtime: Update services independently
- Granular Control: Each container configured explicitly
- Self-Hosted: No external dependencies
Required GitHub Secrets
Configure these in your repository settings:
# Supabase Production
SUPABASE_URL
SUPABASE_ANON_KEY
SUPABASE_SERVICE_KEY
SUPABASE_JWT_SECRET
NEXT_PUBLIC_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_ANON_KEY
# Application
NEXT_PUBLIC_API_URL
BACKEND_CORS_ORIGINS
GHCR_TOKEN # For pulling images
# Datadog
DD_API_KEY
DD_SITE
DD_SERVICE
NEXT_PUBLIC_DD_RUM_APPLICATION_ID
NEXT_PUBLIC_DD_RUM_CLIENT_TOKEN
NEXT_PUBLIC_DD_SITE
NEXT_PUBLIC_DD_SERVICE
# Optional: Database Monitoring
POSTGRES_DATADOG_USERNAME
POSTGRES_DATADOG_PASSWORD
POSTGRES_DATADOG_DBNAME
SUPABASE_METRICS_URL
Manual Container Management
If needed, you can manage containers directly on unRAID:
# View running containers
docker ps
# Update a specific container (example: backend)
docker pull ghcr.io/eddie-rowe/vertical-farm/backend:latest
docker rm -f backend
docker run -d --name backend --network vertical-farm-network \
-p 8000:8000 \
-e SUPABASE_URL=... \
# ... other env vars
ghcr.io/eddie-rowe/vertical-farm/backend:latest
Environment Variables
Local Development (.env.local)
Created automatically by setup script:
# Supabase Local (auto-populated)
SUPABASE_URL=http://localhost:54321
SUPABASE_ANON_KEY=<auto-generated>
SUPABASE_SERVICE_KEY=<auto-generated>
# Application
PROJECT_NAME=vertical-farm-local
DEBUG=true
ENVIRONMENT=local
Production Environment
Production environment variables are managed entirely through: - GitHub Secrets: Stored securely in repository settings - GitHub Actions Variables: For non-sensitive configuration - Self-hosted Runner: Accesses secrets during deployment
No .env
files are used in production for security reasons.
Key Differences: Local vs Production
Aspect | Local Development | Production |
---|---|---|
Deployment Method | docker-compose | Individual docker run commands |
Supabase | Local CLI instance | Cloud instance |
Hot Reload | Enabled (volume mounts) | Disabled |
Debug Mode | True | False |
Container Management | Docker Compose | unRAID + GitHub Actions |
Images | Built locally | Pulled from GHCR |
Datadog | Optional (profile) | Always enabled |
Runner | Local machine | Self-hosted on unRAID |
Network | Bridge network | vertical-farm-network |
Updates | Manual restart | Zero-downtime via workflow |
Troubleshooting
Local Development Issues
Supabase won't start:
# Check status
supabase status
# Reset if needed
supabase stop
supabase start
Port conflicts:
# Check what's using the port
lsof -i :3000 # or :8000, :54321
# Change ports in docker-compose.local.yml if needed
Can't connect to Supabase from container:
- Ensure host.docker.internal
is used in container environment
- Check that Supabase is running: supabase status
Production Issues
Deployment fails:
- Check GitHub Actions logs in deploy-unraid.yml
workflow
- Verify all secrets are set in repository settings
- Ensure self-hosted runner is online
- Check unRAID server resources
Services unhealthy:
# Check container logs (on unRAID)
docker logs backend --tail=100
docker logs frontend --tail=100
docker logs dd-agent --tail=100
# Restart specific service
docker restart backend
# Manual redeploy
docker rm -f backend
docker run -d --name backend ... # with all env vars
unRAID Specific:
- Check unRAID Docker tab for container status
- Verify network vertical-farm-network
exists
- Ensure ports 3000, 8000, 8126 are not conflicting
Best Practices
- Never commit
.env
files - Use.env.example
as templates - Test locally first - Always verify changes work with
make up
- Use health checks - Production containers should define health checks
- Monitor deployments - Check Datadog after deployments
- Keep images small - Use multi-stage builds in Dockerfiles
- Version your deployments - Use git SHA as Docker tags
Migration Guide
If you're updating from the old single docker-compose.yml
:
- Pull latest changes
- Stop existing containers:
docker-compose down
- Run the new setup:
make up
- Local development now uses
docker-compose.local.yml
- Production continues using the unRAID workflow
[[memory:6973530]]