Some checks failed
Dev Deployment (Zero Downtime) / deploy-dev (push) Has been cancelled
- Created separate workflows for production and dev deployments - Production branch → dk0.dev (port 3000) - Dev branch → dev.dk0.dev (port 3002) - Zero-downtime deployment pattern (start new, wait for health, remove old) - Complete isolation between environments (separate containers, databases, networks) - Cleaned up unused code and files: - Removed unused GhostEditor and ResizableGhostEditor components - Removed old/unused workflows and markdown files - Fixed docker-compose references - Upgraded dependencies to latest compatible versions - Fixed TypeScript errors in editor page - Updated staging to use dev.dk0.dev domain
201 lines
5.2 KiB
Markdown
201 lines
5.2 KiB
Markdown
# 🚀 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 <container-name>`
|
|
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)
|