# 🚀 Deployment Setup Guide ## Overview This project uses a **dual-branch deployment strategy** with zero-downtime deployments: - **Production Branch** (`production`) → Serves `https://dk0.dev` on port 3000 - **Dev Branch** (`dev`) → Serves `https://dev.dk0.dev` on port 3002 Both environments are completely isolated with separate: - Docker containers - Databases (PostgreSQL) - Redis instances - Networks - Volumes ## Branch Strategy ### Production Branch - **Branch**: `production` - **Domain**: `https://dk0.dev` - **Port**: `3000` - **Container**: `portfolio-app` - **Database**: `portfolio_db` (port 5432) - **Redis**: `portfolio-redis` (port 6379) - **Image Tag**: `portfolio-app:production` / `portfolio-app:latest` ### Dev Branch - **Branch**: `dev` - **Domain**: `https://dev.dk0.dev` - **Port**: `3002` - **Container**: `portfolio-app-staging` - **Database**: `portfolio_staging_db` (port 5434) - **Redis**: `portfolio-redis-staging` (port 6381) - **Image Tag**: `portfolio-app:staging` ## Automatic Deployment ### How It Works 1. **Push to `production` branch**: - Triggers `.gitea/workflows/production-deploy.yml` - Runs tests, builds, and deploys to production - Zero-downtime deployment (starts new container, waits for health, removes old) 2. **Push to `dev` branch**: - Triggers `.gitea/workflows/dev-deploy.yml` - Runs tests, builds, and deploys to dev/staging - Zero-downtime deployment ### Zero-Downtime Process 1. Build new Docker image 2. Start new container with updated image 3. Wait for new container to be healthy (health checks) 4. Verify HTTP endpoints respond correctly 5. Remove old container (if different) 6. Cleanup old images ## Manual Deployment ### Production ```bash # Build and deploy production docker build -t portfolio-app:latest . docker compose -f docker-compose.production.yml up -d --build ``` ### Dev/Staging ```bash # Build and deploy dev docker build -t portfolio-app:staging . docker compose -f docker-compose.staging.yml up -d --build ``` ## Environment Variables ### Required Gitea Variables - `NEXT_PUBLIC_BASE_URL` - Base URL for the application - `MY_EMAIL` - Email address for contact - `MY_INFO_EMAIL` - Info email address - `LOG_LEVEL` - Logging level (info/debug) ### Required Gitea Secrets - `MY_PASSWORD` - Email password - `MY_INFO_PASSWORD` - Info email password - `ADMIN_BASIC_AUTH` - Admin basic auth credentials - `N8N_SECRET_TOKEN` - Optional: n8n webhook secret ### Optional Variables - `N8N_WEBHOOK_URL` - n8n webhook URL for automation ## Health Checks Both environments have health check endpoints: - Production: `http://localhost:3000/api/health` - Dev: `http://localhost:3002/api/health` ## Monitoring ### Check Container Status ```bash # Production docker compose -f docker-compose.production.yml ps # Dev docker compose -f docker-compose.staging.yml ps ``` ### View Logs ```bash # Production docker logs portfolio-app --tail=100 -f # Dev docker logs portfolio-app-staging --tail=100 -f ``` ### Health Check ```bash # Production curl http://localhost:3000/api/health # Dev curl http://localhost:3002/api/health ``` ## Troubleshooting ### Container Won't Start 1. Check logs: `docker logs ` 2. Verify environment variables are set 3. Check database/redis connectivity 4. Verify ports aren't already in use ### Deployment Fails 1. Check Gitea Actions logs 2. Verify all required secrets/variables are set 3. Check if old containers are blocking ports 4. Verify Docker image builds successfully ### Zero-Downtime Issues - Old container might still be running - check with `docker ps` - Health checks might be failing - check container logs - Port conflicts - verify ports 3000 and 3002 are available ## Rollback If a deployment fails or causes issues: ```bash # Production rollback docker compose -f docker-compose.production.yml down docker tag portfolio-app:previous portfolio-app:latest docker compose -f docker-compose.production.yml up -d # Dev rollback docker compose -f docker-compose.staging.yml down docker tag portfolio-app:staging-previous portfolio-app:staging docker compose -f docker-compose.staging.yml up -d ``` ## Best Practices 1. **Always test on dev branch first** before pushing to production 2. **Monitor health checks** after deployment 3. **Keep old images** for quick rollback (last 3 versions) 4. **Use feature flags** for new features 5. **Document breaking changes** before deploying 6. **Run tests locally** before pushing ## Network Configuration - **Production Network**: `portfolio_net` + `proxy` (external) - **Dev Network**: `portfolio_staging_net` - **Isolation**: Complete separation ensures no interference ## Database Management ### Production Database - **Container**: `portfolio-postgres` - **Port**: `5432` (internal only) - **Database**: `portfolio_db` - **User**: `portfolio_user` ### Dev Database - **Container**: `portfolio-postgres-staging` - **Port**: `5434` (external), `5432` (internal) - **Database**: `portfolio_staging_db` - **User**: `portfolio_user` ## Redis Configuration ### Production Redis - **Container**: `portfolio-redis` - **Port**: `6379` (internal only) ### Dev Redis - **Container**: `portfolio-redis-staging` - **Port**: `6381` (external), `6379` (internal)