feat: add multi-environment deployment with Gitea Actions & Dokploy
- 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
This commit is contained in:
401
docs/DOKPLOY_DEPLOYMENT.md
Normal file
401
docs/DOKPLOY_DEPLOYMENT.md
Normal file
@@ -0,0 +1,401 @@
|
||||
# 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=<your-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 <commit-sha>
|
||||
|
||||
# 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=<your-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.
|
||||
Reference in New Issue
Block a user