# Dokploy Deployment Guide ## Overview This project uses **Gitea Actions** to build Docker images and **Dokploy** to deploy them. Each branch (dev, staging, main) has its own: - Docker image tag - Docker Compose file - Dokploy application - Domain --- ## Architecture ``` ┌─────────────┐ │ Gitea │ │ (Source) │ └──────┬──────┘ │ push event ↓ ┌─────────────┐ │ Gitea │ │ Actions │ Builds Docker images │ (CI/CD) │ Tags: dev, staging, latest └──────┬──────┘ │ ↓ ┌─────────────┐ │ Gitea │ │ Registry │ git.app.flexinit.nl/oussamadouhou/ai-stack-deployer └──────┬──────┘ │ webhook (push event) ↓ ┌─────────────┐ │ Dokploy │ Pulls & deploys image │ (Deploy) │ Uses docker-compose.{env}.yml └─────────────┘ ``` --- ## Branch Strategy | Branch | Image Tag | Compose File | Domain (suggested) | |-----------|-----------|----------------------------|------------------------------| | `dev` | `dev` | `docker-compose.dev.yml` | portal-dev.ai.flexinit.nl | | `staging` | `staging` | `docker-compose.staging.yml` | portal-staging.ai.flexinit.nl | | `main` | `latest` | `docker-compose.prod.yml` | portal.ai.flexinit.nl | --- ## Gitea Actions Workflow **File**: `.gitea/workflows/docker-publish.yaml` **Triggers**: Push to `dev`, `staging`, or `main` branches **Builds**: ```yaml dev branch → git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:dev staging branch → git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:staging main branch → git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:latest ``` **Also creates SHA tags**: `{branch}-{short-sha}` --- ## Docker Compose Files ### `docker-compose.dev.yml` - Pulls: `git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:dev` - Environment: `NODE_ENV=development` - Container name: `ai-stack-deployer-dev` ### `docker-compose.staging.yml` - Pulls: `git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:staging` - Environment: `NODE_ENV=staging` - Container name: `ai-stack-deployer-staging` ### `docker-compose.prod.yml` - Pulls: `git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:latest` - Environment: `NODE_ENV=production` - Container name: `ai-stack-deployer` ### `docker-compose.local.yml` - **Builds locally** (doesn't pull from registry) - For local development only - Includes volume mounts for hot reload --- ## Setting Up Dokploy ### Step 1: Create Dev Application 1. **In Dokploy UI**, create new application: - **Name**: `ai-stack-deployer-dev` - **Type**: Docker Compose - **Repository**: `ssh://git@git.app.flexinit.nl:22222/oussamadouhou/ai-stack-deployer.git` - **Branch**: `dev` - **Compose File**: `docker-compose.dev.yml` 2. **Configure Domain**: - Add domain: `portal-dev.ai.flexinit.nl` - Enable SSL (via Traefik wildcard cert) 3. **Set Environment Variables**: ```env DOKPLOY_URL=http://10.100.0.20:3000 DOKPLOY_API_TOKEN= STACK_DOMAIN_SUFFIX=ai.flexinit.nl STACK_IMAGE=git.app.flexinit.nl/flexinit/agent-stack:latest ``` 4. **Configure Webhook**: - Event: **Push** - Branch: `dev` - This will auto-deploy when you push to dev branch 5. **Deploy** ### Step 2: Create Staging Application Repeat Step 1 with these changes: - **Name**: `ai-stack-deployer-staging` - **Branch**: `staging` - **Compose File**: `docker-compose.staging.yml` - **Domain**: `portal-staging.ai.flexinit.nl` - **Webhook Branch**: `staging` ### Step 3: Create Production Application Repeat Step 1 with these changes: - **Name**: `ai-stack-deployer-prod` - **Branch**: `main` - **Compose File**: `docker-compose.prod.yml` - **Domain**: `portal.ai.flexinit.nl` - **Webhook Branch**: `main` --- ## Deployment Workflow ### Development Cycle ```bash # 1. Make changes on dev branch git checkout dev # ... make changes ... git commit -m "feat: add new feature" git push origin dev # 2. Gitea Actions automatically builds dev image # 3. Dokploy webhook triggers and deploys to portal-dev.ai.flexinit.nl # 4. Test on dev environment curl https://portal-dev.ai.flexinit.nl/health # 5. When ready, merge to staging git checkout staging git merge dev git push origin staging # 6. Gitea Actions builds staging image # 7. Dokploy deploys to portal-staging.ai.flexinit.nl # 8. Final testing on staging, then merge to main git checkout main git merge staging git push origin main # 9. Gitea Actions builds production image (latest) # 10. Dokploy deploys to portal.ai.flexinit.nl ``` --- ## Image Tags Explained Each push creates multiple tags: ### Example: Push to `dev` branch (commit `abc1234`) Gitea Actions creates: ``` git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:dev ← Latest dev git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:dev-abc1234 ← Specific commit ``` ### Example: Push to `main` branch (commit `xyz5678`) Gitea Actions creates: ``` git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:latest ← Latest production git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:main-xyz5678 ← Specific commit ``` **Why?** - Branch tags (`dev`, `staging`, `latest`) always point to latest build - SHA tags allow you to rollback to specific commits if needed --- ## Rollback Strategy ### Quick Rollback in Dokploy If a deployment breaks, you can quickly rollback: 1. **In Dokploy UI**, go to the application 2. **Edit** the docker-compose file 3. Change the image tag to a previous SHA: ```yaml image: git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:main-abc1234 ``` 4. **Redeploy** ### Manual Rollback via Git ```bash # Find the last working commit git log --oneline # Revert to that commit git revert HEAD # or git reset --hard # Push to trigger rebuild git push origin main ``` --- ## Local Development ### Using docker-compose.local.yml ```bash # Build and run locally docker-compose -f docker-compose.local.yml up -d # View logs docker-compose -f docker-compose.local.yml logs -f # Stop docker-compose -f docker-compose.local.yml down ``` ### Using Bun directly (without Docker) ```bash # Install dependencies bun install # Run dev server (API + Vite) bun run dev # Run API only bun run dev:api # Run client only bun run dev:client ``` --- ## Environment Variables ### Required in Dokploy ```env DOKPLOY_URL=http://10.100.0.20:3000 DOKPLOY_API_TOKEN= ``` ### Optional (with defaults) ```env PORT=3000 HOST=0.0.0.0 STACK_DOMAIN_SUFFIX=ai.flexinit.nl STACK_IMAGE=git.app.flexinit.nl/flexinit/agent-stack:latest RESERVED_NAMES=admin,api,www,root,system,test,demo,portal ``` ### Per-Environment Overrides If dev/staging/prod need different configs, set them in Dokploy: **Dev**: ```env STACK_DOMAIN_SUFFIX=dev-ai.flexinit.nl ``` **Staging**: ```env STACK_DOMAIN_SUFFIX=staging-ai.flexinit.nl ``` **Prod**: ```env STACK_DOMAIN_SUFFIX=ai.flexinit.nl ``` --- ## Troubleshooting ### Build Fails in Gitea Actions Check the workflow logs in Gitea: ``` https://git.app.flexinit.nl/oussamadouhou/ai-stack-deployer/actions ``` Common issues: - **AVX error**: Fixed in Dockerfile (uses Node.js for build) - **Registry auth**: Check `REGISTRY_TOKEN` secret in Gitea ### Deployment Fails in Dokploy 1. **Check Dokploy logs**: Application → Logs 2. **Verify image exists**: ```bash docker pull git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:dev ``` 3. **Check environment variables**: Make sure all required vars are set ### Health Check Failing ```bash # SSH into Dokploy host ssh user@10.100.0.20 # Check container logs docker logs ai-stack-deployer-dev # Test health endpoint curl http://localhost:3000/health ``` ### Webhook Not Triggering 1. **In Dokploy**, check webhook configuration 2. **In Gitea**, go to repo Settings → Webhooks 3. Verify webhook URL and secret match 4. Check recent deliveries for errors --- ## Production Considerations ### 1. Image Size Optimization The Docker image excludes dev files via `.dockerignore`: - ✅ `docs/` - excluded - ✅ `scripts/` - excluded - ✅ `.gitea/` - excluded - ✅ `*.md` (except README.md) - excluded Current image size: ~150MB ### 2. Security - Container runs as non-root user (`nodejs:1001`) - No secrets in source code (uses `.env`) - Dokploy API accessible only on internal network ### 3. Monitoring Set up alerts for: - Container health check failures - Memory/CPU usage spikes - Deployment failures ### 4. Backup Strategy - **Database**: This app has no database (stateless) - **Configuration**: Environment variables stored in Dokploy (backed up) - **Code**: Stored in Gitea (backed up) --- ## Summary | Environment | Domain | Image Tag | Auto-Deploy? | |-------------|------------------------------|-----------|--------------| | Dev | portal-dev.ai.flexinit.nl | `dev` | ✅ On push | | Staging | portal-staging.ai.flexinit.nl | `staging` | ✅ On push | | Production | portal.ai.flexinit.nl | `latest` | ✅ On push | **Next Steps**: 1. ✅ Push changes to `dev` branch 2. ⏳ Create 3 Dokploy applications (dev, staging, prod) 3. ⏳ Configure webhooks for each branch 4. ⏳ Deploy and test each environment --- **Questions?** Check the main README.md or CLAUDE.md for more details.