xiaohongshu
xiaohongshu
dokploy-multi-tenant
Multi-tenancy patterns for Dokploy templates with network isolation: separate docker networks per tenant, shared infrastructure, and tenant-specific configuration.
Full skill instructions
This implementation uses separate Docker networks per tenant with shared infrastructure:
┌────────────────────────────────────────────────────────────────┐
│ Shared Infrastructure │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Traefik │ │ Monitoring │ │ Logging │ │
│ │ (dokploy) │ │ (shared) │ │ (shared) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │
│ │ dokploy-network │
└─────────┼──────────────────────────────────────────────────────┘
│
┌─────┴─────┬─────────────┬─────────────┐
│ │ │ │
┌───┴───┐ ┌───┴───┐ ┌───┴───┐ ┌───┴───┐
│Tenant1│ │Tenant2│ │Tenant3│ │TenantN│
│ net │ │ net │ │ net │ │ net │
│ │ │ │ │ │ │ │
│ ┌───┐ │ │ ┌───┐ │ │ ┌───┐ │ │ ┌───┐ │
│ │App│ │ │ │App│ │ │ │App│ │ │ │App│ │
│ │DB │ │ │ │DB │ │ │ │DB │ │ │ │DB │ │
│ └───┘ │ │ └───┘ │ │ └───┘ │ │ └───┘ │
└───────┘ └───────┘ └───────┘ └───────┘
Characteristics:
networks:
${TENANT_ID}-net:
driver: bridge
dokploy-network:
external: true
Naming Convention:
${tenant_id}-${app_name}-net or ${tenant_id}-netacme-corp-net, client-a-net, project-123-netSubdomain per Tenant:
# tenant1.example.com
# tenant2.example.com
labels:
- "traefik.http.routers.${TENANT_ID}.rule=Host(`${TENANT_ID}.${BASE_DOMAIN}`)"
Custom Domain per Tenant:
# app.tenant1.com
# app.tenant2.com
labels:
- "traefik.http.routers.${TENANT_ID}.rule=Host(`${TENANT_DOMAIN}`)"
Path-Based Tenancy (Not Recommended):
# example.com/tenant1
# example.com/tenant2
labels:
- "traefik.http.routers.${TENANT_ID}.rule=Host(`${DOMAIN}`) && PathPrefix(`/${TENANT_ID}`)"
services:
app:
environment:
TENANT_ID: ${TENANT_ID:?Set tenant identifier}
TENANT_NAME: ${TENANT_NAME:?Set tenant name}
TENANT_DOMAIN: ${TENANT_DOMAIN:?Set tenant domain}
volumes:
${TENANT_ID}-app-data:
driver: local
${TENANT_ID}-postgres-data:
driver: local
Naming Convention:
${tenant_id}-${service}-${type}acme-corp-postgres-data, client-a-app-uploadsservices:
app:
image: myapp:1.0.0
restart: always
depends_on:
postgres:
condition: service_healthy
environment:
# Tenant identification
TENANT_ID: ${TENANT_ID:?Set tenant identifier}
TENANT_NAME: ${TENANT_NAME:-${TENANT_ID}}
# Domain
APP_DOMAIN: ${TENANT_DOMAIN:?Set tenant domain}
APP_URL: https://${TENANT_DOMAIN}
# Database
DATABASE_URL: postgresql://${DB_USER:-app}:${DB_PASS}@postgres:5432/${DB_NAME:-app}
# Security
SECRET_KEY: ${SECRET_KEY:?Set secret key}
networks:
- ${TENANT_ID}-net
- dokploy-network
labels:
- "traefik.enable=true"
- "traefik.http.routers.${TENANT_ID}-app.rule=Host(`${TENANT_DOMAIN}`)"
- "traefik.http.routers.${TENANT_ID}-app.entrypoints=websecure"
- "traefik.http.routers.${TENANT_ID}-app.tls.certresolver=letsencrypt"
- "traefik.http.services.${TENANT_ID}-app.loadbalancer.server.port=8080"
- "traefik.docker.network=dokploy-network"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
postgres:
image: postgres:16-alpine
restart: always
volumes:
- ${TENANT_ID}-postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_DB: ${DB_NAME:-app}
POSTGRES_USER: ${DB_USER:-app}
POSTGRES_PASSWORD: ${DB_PASS:?Set database password}
networks:
- ${TENANT_ID}-net
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-app} -d ${DB_NAME:-app}"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
volumes:
${TENANT_ID}-postgres-data:
driver: local
networks:
${TENANT_ID}-net:
driver: bridge
dokploy-network:
external: true
# Multi-Tenant Application Template
# Each deployment creates an isolated tenant environment
[variables]
tenant_id = "${username}" # User provides tenant identifier
tenant_domain = "${domain}"
db_password = "${password:32}"
secret_key = "${base64:64}"
[[config.domains]]
serviceName = "app"
port = 8080
host = "${tenant_domain}"
[config.env]
# ===========================================
# Tenant Configuration
# ===========================================
TENANT_ID = "${tenant_id}"
TENANT_NAME = "${tenant_id}"
TENANT_DOMAIN = "${tenant_domain}"
# ===========================================
# Database
# ===========================================
DB_NAME = "app"
DB_USER = "app"
DB_PASS = "${db_password}"
POSTGRES_DB = "app"
POSTGRES_USER = "app"
POSTGRES_PASSWORD = "${db_password}"
# ===========================================
# Security
# ===========================================
SECRET_KEY = "${secret_key}"
Each tenant gets tenant.example.com:
# Dokploy deployment for Tenant "acme"
[config.env]
TENANT_ID = "acme"
TENANT_DOMAIN = "acme.example.com"
DNS Setup:
*.example.com → Your Dokploy server
Each tenant brings their own domain:
# Dokploy deployment for Tenant with custom domain
[config.env]
TENANT_ID = "acme"
TENANT_DOMAIN = "app.acmecorp.com"
DNS Setup (per tenant):
app.acmecorp.com CNAME your-dokploy-server.example.com
Each project is a tenant:
[config.env]
TENANT_ID = "project-123"
TENANT_DOMAIN = "project-123.projects.example.com"
| Resource | Shared | Notes |
|---|---|---|
| Traefik | Yes | Single instance routes all tenants |
| Monitoring | Yes | Central Prometheus/Grafana |
| Logging | Yes | Central logging stack |
| SSL Certs | Yes | LetsEncrypt for all |
| Resource | Isolated | Notes |
|---|---|---|
| Docker Network | Yes | Tenant-specific network |
| Database | Yes | Dedicated database per tenant |
| Volumes | Yes | Tenant-specific volumes |
| CPU/Memory | Optional | Use resource limits |
${tenant_id}-net or ${tenant_id}-${app}-net${tenant_id}-${service}-data${tenant_id}-${service}Issue: Two tenants with same router name conflict Solution: Include tenant ID in all router names
Issue: Tenants overwrite each other's data Solution: Include tenant ID in volume names
Issue: Tenants can access each other's services Solution: Each tenant on separate network
Issue: Can't deploy multiple instances
Solution: Use ${TENANT_ID} variable everywhere
To convert existing single-tenant template:
[variables]
tenant_id = "${username}"
networks:
${TENANT_ID}-net: # Was: app-net
driver: bridge
volumes:
${TENANT_ID}-postgres-data: # Was: postgres-data
driver: local
labels:
- "traefik.http.routers.${TENANT_ID}-app.rule=..." # Was: app
environment:
TENANT_DOMAIN: ${TENANT_DOMAIN:?Set tenant domain}
This skill is part of the skills-first architecture - an advanced pattern loaded when multi-tenant architecture is specifically required (not part of standard workflow).
dokploy-compose-structure: Network patternsdokploy-traefik-routing: Domain routingdokploy-environment-config: Tenant variablesdokploy-multi-service: Multi-service dependency patterns/dokploy-create workflow/dokploy-create workflowSee: /dokploy-create for standard workflow, this skill for multi-tenant variants
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience