- Update Gitea workflow to build dev/staging/main branches
- Create environment-specific docker-compose files
- docker-compose.dev.yml (pulls dev image)
- docker-compose.staging.yml (pulls staging image)
- docker-compose.prod.yml (pulls latest image)
- docker-compose.local.yml (builds locally for development)
- Remove generic docker-compose.yml (replaced by env-specific files)
- Update .dockerignore to exclude docs/ and .gitea/ from production images
- Add comprehensive deployment guide (docs/DOKPLOY_DEPLOYMENT.md)
Image Tags:
- dev branch → :dev
- staging branch → :staging
- main branch → :latest
- All branches → :{branch}-{sha}
Benefits:
- Separate deployments for dev/staging/prod
- Automated CI/CD via Gitea Actions + Dokploy webhooks
- Leaner production images (excludes dev tools/docs)
- Local development support (docker-compose.local.yml)
- Rollback support via SHA-tagged images
9.4 KiB
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:
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
-
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
- Name:
-
Configure Domain:
- Add domain:
portal-dev.ai.flexinit.nl - Enable SSL (via Traefik wildcard cert)
- Add domain:
-
Set Environment Variables:
DOKPLOY_URL=http://10.100.0.20:3000 DOKPLOY_API_TOKEN=<your-token> STACK_DOMAIN_SUFFIX=ai.flexinit.nl STACK_IMAGE=git.app.flexinit.nl/flexinit/agent-stack:latest -
Configure Webhook:
- Event: Push
- Branch:
dev - This will auto-deploy when you push to dev branch
-
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
# 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:
- In Dokploy UI, go to the application
- Edit the docker-compose file
- Change the image tag to a previous SHA:
image: git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:main-abc1234 - Redeploy
Manual Rollback via Git
# Find the last working commit
git log --oneline
# Revert to that commit
git revert HEAD # or git reset --hard <commit-sha>
# Push to trigger rebuild
git push origin main
Local Development
Using docker-compose.local.yml
# 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)
# 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
DOKPLOY_URL=http://10.100.0.20:3000
DOKPLOY_API_TOKEN=<your-token>
Optional (with defaults)
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:
STACK_DOMAIN_SUFFIX=dev-ai.flexinit.nl
Staging:
STACK_DOMAIN_SUFFIX=staging-ai.flexinit.nl
Prod:
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_TOKENsecret in Gitea
Deployment Fails in Dokploy
- Check Dokploy logs: Application → Logs
- Verify image exists:
docker pull git.app.flexinit.nl/oussamadouhou/ai-stack-deployer:dev - Check environment variables: Make sure all required vars are set
Health Check Failing
# 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
- In Dokploy, check webhook configuration
- In Gitea, go to repo Settings → Webhooks
- Verify webhook URL and secret match
- 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:
- ✅ Push changes to
devbranch - ⏳ Create 3 Dokploy applications (dev, staging, prod)
- ⏳ Configure webhooks for each branch
- ⏳ Deploy and test each environment
Questions? Check the main README.md or CLAUDE.md for more details.