- 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
402 lines
9.4 KiB
Markdown
402 lines
9.4 KiB
Markdown
# 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.
|