docs: Add comprehensive Dokploy deployment guide for Plane#8605
docs: Add comprehensive Dokploy deployment guide for Plane#8605andyng2410 wants to merge 1 commit intomakeplane:previewfrom
Conversation
Add comprehensive guide for deploying Plane on Dokploy with 3 approaches: - Docker Compose from Git repo (recommended) - AIO (All-In-One) pre-built image - Compose with pre-built images (no build required) https://claude.ai/code/session_01CTtRjowgPvFWBCESwRbHRx
|
|
📝 WalkthroughWalkthroughA new comprehensive deployment guide for Plane on Dokploy is introduced, documenting system architecture, three deployment options (Docker Compose via Dokploy, AIO image, and pre-built images), environment configuration, domain setup with Traefik, troubleshooting procedures, and version update workflows. Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Fix all issues with AI agents
In `@deployments/dokploy/DEPLOY.md`:
- Around line 132-133: Add a short guidance block under the SECRET_KEY and
LIVE_SERVER_SECRET_KEY entries explaining how to generate cryptographically
secure keys; mention using Django's get_random_secret_key (via a small python
one-liner) and an alternative using openssl rand -base64 50, and note that keys
should be at least 50 random characters and kept secret—update the DEPLOY.md
text around the SECRET_KEY and LIVE_SERVER_SECRET_KEY references to include this
guidance.
- Around line 493-494: Add explicit guidance beside the SECRET_KEY and
LIVE_SERVER_SECRET_KEY examples: explain they must be cryptographically secure
random strings (suggest length e.g., 50+ chars), show secure generation commands
(for example use openssl rand -base64 50 or Python: python -c "import secrets;
print(secrets.token_urlsafe(50))"), instruct readers to store them in
environment variables or a .env file and never commit them to source control,
and note that LIVE_SERVER_SECRET_KEY should be different from SECRET_KEY and
kept secret for production use; update the text around the SECRET_KEY and
LIVE_SERVER_SECRET_KEY examples accordingly.
- Line 211: Replace the floating tag `:latest` on the Plane image reference
`artifacts.plane.so/makeplane/plane-aio-community:latest` with a pinned tag
(e.g., `:stable` or a specific semver like `:v1.2.0`) and do the same for all
other image references in the pre-built compose section (the referenced
pre-built compose image list) so every container image uses a fixed version;
update deployment docs/examples to show the pinned tag and mention how to
choose/update the pinned version.
🧹 Nitpick comments (2)
deployments/dokploy/DEPLOY.md (2)
10-10: Optional: Fix table formatting for consistency.The table has spacing inconsistencies around the pipe separators. Consider adjusting for better formatting compliance.
✨ Proposed formatting fix
-|---------|--------|-------------| +| ------- | ------ | ----------- |Apply similar spacing to line 527 as well.
189-193: Add language identifier to code block.For better syntax highlighting and clarity, specify
bashas the language identifier.✨ Proposed fix
- ``` + ```bash RABBITMQ_DEFAULT_USER=planeApply similarly to code blocks at lines 200 and 514.
| - SECRET_KEY=<django-secret-key-ngẫu-nhiên-50-ký-tự> | ||
| - LIVE_SERVER_SECRET_KEY=<random-key> |
There was a problem hiding this comment.
Add guidance for generating SECRET_KEY.
The documentation references SECRET_KEY and LIVE_SERVER_SECRET_KEY but doesn't provide instructions for generating cryptographically secure values. Django's SECRET_KEY should be a random string of at least 50 characters.
📝 Suggested addition
Consider adding a note like:
> **Tạo SECRET_KEY an toàn:**
> ```bash
> python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
> ```
> hoặc dùng: `openssl rand -base64 50`🤖 Prompt for AI Agents
In `@deployments/dokploy/DEPLOY.md` around lines 132 - 133, Add a short guidance
block under the SECRET_KEY and LIVE_SERVER_SECRET_KEY entries explaining how to
generate cryptographically secure keys; mention using Django's
get_random_secret_key (via a small python one-liner) and an alternative using
openssl rand -base64 50, and note that keys should be at least 50 random
characters and kept secret—update the DEPLOY.md text around the SECRET_KEY and
LIVE_SERVER_SECRET_KEY references to include this guidance.
|
|
||
| 1. Trong project, nhấn **+ Add Service** → **Docker** | ||
| 2. Chọn source: **Docker Image** | ||
| 3. Image: `artifacts.plane.so/makeplane/plane-aio-community:latest` |
There was a problem hiding this comment.
Recommend version pinning instead of :latest tag.
Using :latest tag for production deployments can lead to unpredictable behavior, breaking changes, and difficult rollbacks. Consider specifying a stable version tag.
Example:
image: artifacts.plane.so/makeplane/plane-aio-community:stable
# or a specific version like:
image: artifacts.plane.so/makeplane/plane-aio-community:v1.2.0This same concern applies to all image references in the pre-built compose approach (lines 253-458).
🤖 Prompt for AI Agents
In `@deployments/dokploy/DEPLOY.md` at line 211, Replace the floating tag
`:latest` on the Plane image reference
`artifacts.plane.so/makeplane/plane-aio-community:latest` with a pinned tag
(e.g., `:stable` or a specific semver like `:v1.2.0`) and do the same for all
other image references in the pre-built compose section (the referenced
pre-built compose image list) so every container image uses a fixed version;
update deployment docs/examples to show the pinned tag and mention how to
choose/update the pinned version.
| image: artifacts.plane.so/makeplane/plane-frontend:latest | ||
| restart: always | ||
| depends_on: | ||
| - api | ||
|
|
||
| admin: | ||
| image: artifacts.plane.so/makeplane/plane-admin:latest | ||
| restart: always | ||
| depends_on: | ||
| - api | ||
|
|
||
| space: | ||
| image: artifacts.plane.so/makeplane/plane-space:latest | ||
| restart: always | ||
| depends_on: | ||
| - api | ||
|
|
||
| api: | ||
| image: artifacts.plane.so/makeplane/plane-backend:latest | ||
| restart: always | ||
| command: ./bin/docker-entrypoint-api.sh | ||
| environment: | ||
| - DEBUG=0 | ||
| - POSTGRES_USER=${POSTGRES_USER} | ||
| - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} | ||
| - POSTGRES_HOST=plane-db | ||
| - POSTGRES_DB=${POSTGRES_DB} | ||
| - POSTGRES_PORT=5432 | ||
| - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@plane-db:5432/${POSTGRES_DB} | ||
| - REDIS_HOST=plane-redis | ||
| - REDIS_PORT=6379 | ||
| - REDIS_URL=redis://plane-redis:6379/ | ||
| - RABBITMQ_HOST=plane-mq | ||
| - RABBITMQ_PORT=5672 | ||
| - RABBITMQ_USER=${RABBITMQ_USER} | ||
| - RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD} | ||
| - RABBITMQ_VHOST=${RABBITMQ_VHOST} | ||
| - SECRET_KEY=${SECRET_KEY} | ||
| - LIVE_SERVER_SECRET_KEY=${LIVE_SERVER_SECRET_KEY} | ||
| - AWS_REGION=${AWS_REGION} | ||
| - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} | ||
| - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} | ||
| - AWS_S3_ENDPOINT_URL=http://plane-minio:9000 | ||
| - AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME} | ||
| - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT} | ||
| - USE_MINIO=1 | ||
| - MINIO_ENDPOINT_SSL=0 | ||
| - WEB_URL=${WEB_URL} | ||
| - CORS_ALLOWED_ORIGINS=${WEB_URL} | ||
| - GUNICORN_WORKERS=2 | ||
| - API_KEY_RATE_LIMIT=${API_KEY_RATE_LIMIT} | ||
| depends_on: | ||
| - plane-db | ||
| - plane-redis | ||
|
|
||
| worker: | ||
| image: artifacts.plane.so/makeplane/plane-backend:latest | ||
| restart: always | ||
| command: ./bin/docker-entrypoint-worker.sh | ||
| environment: | ||
| - DEBUG=0 | ||
| - POSTGRES_USER=${POSTGRES_USER} | ||
| - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} | ||
| - POSTGRES_HOST=plane-db | ||
| - POSTGRES_DB=${POSTGRES_DB} | ||
| - POSTGRES_PORT=5432 | ||
| - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@plane-db:5432/${POSTGRES_DB} | ||
| - REDIS_HOST=plane-redis | ||
| - REDIS_PORT=6379 | ||
| - REDIS_URL=redis://plane-redis:6379/ | ||
| - RABBITMQ_HOST=plane-mq | ||
| - RABBITMQ_PORT=5672 | ||
| - RABBITMQ_USER=${RABBITMQ_USER} | ||
| - RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD} | ||
| - RABBITMQ_VHOST=${RABBITMQ_VHOST} | ||
| - SECRET_KEY=${SECRET_KEY} | ||
| - LIVE_SERVER_SECRET_KEY=${LIVE_SERVER_SECRET_KEY} | ||
| - AWS_REGION=${AWS_REGION} | ||
| - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} | ||
| - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} | ||
| - AWS_S3_ENDPOINT_URL=http://plane-minio:9000 | ||
| - AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME} | ||
| - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT} | ||
| - USE_MINIO=1 | ||
| - MINIO_ENDPOINT_SSL=0 | ||
| - WEB_URL=${WEB_URL} | ||
| - GUNICORN_WORKERS=2 | ||
| - API_KEY_RATE_LIMIT=${API_KEY_RATE_LIMIT} | ||
| depends_on: | ||
| - api | ||
| - plane-db | ||
| - plane-redis | ||
|
|
||
| beat-worker: | ||
| image: artifacts.plane.so/makeplane/plane-backend:latest | ||
| restart: always | ||
| command: ./bin/docker-entrypoint-beat.sh | ||
| environment: | ||
| - DEBUG=0 | ||
| - POSTGRES_USER=${POSTGRES_USER} | ||
| - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} | ||
| - POSTGRES_HOST=plane-db | ||
| - POSTGRES_DB=${POSTGRES_DB} | ||
| - POSTGRES_PORT=5432 | ||
| - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@plane-db:5432/${POSTGRES_DB} | ||
| - REDIS_HOST=plane-redis | ||
| - REDIS_PORT=6379 | ||
| - REDIS_URL=redis://plane-redis:6379/ | ||
| - RABBITMQ_HOST=plane-mq | ||
| - RABBITMQ_PORT=5672 | ||
| - RABBITMQ_USER=${RABBITMQ_USER} | ||
| - RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD} | ||
| - RABBITMQ_VHOST=${RABBITMQ_VHOST} | ||
| - SECRET_KEY=${SECRET_KEY} | ||
| - LIVE_SERVER_SECRET_KEY=${LIVE_SERVER_SECRET_KEY} | ||
| - AWS_REGION=${AWS_REGION} | ||
| - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} | ||
| - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} | ||
| - AWS_S3_ENDPOINT_URL=http://plane-minio:9000 | ||
| - AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME} | ||
| - FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT} | ||
| - USE_MINIO=1 | ||
| - MINIO_ENDPOINT_SSL=0 | ||
| - WEB_URL=${WEB_URL} | ||
| - GUNICORN_WORKERS=2 | ||
| - API_KEY_RATE_LIMIT=${API_KEY_RATE_LIMIT} | ||
| depends_on: | ||
| - api | ||
| - plane-db | ||
| - plane-redis | ||
|
|
||
| migrator: | ||
| image: artifacts.plane.so/makeplane/plane-backend:latest | ||
| restart: "no" | ||
| command: ./bin/docker-entrypoint-migrator.sh | ||
| environment: | ||
| - DEBUG=0 | ||
| - POSTGRES_USER=${POSTGRES_USER} | ||
| - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} | ||
| - POSTGRES_HOST=plane-db | ||
| - POSTGRES_DB=${POSTGRES_DB} | ||
| - POSTGRES_PORT=5432 | ||
| - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@plane-db:5432/${POSTGRES_DB} | ||
| - REDIS_HOST=plane-redis | ||
| - REDIS_PORT=6379 | ||
| - REDIS_URL=redis://plane-redis:6379/ | ||
| - RABBITMQ_HOST=plane-mq | ||
| - RABBITMQ_PORT=5672 | ||
| - RABBITMQ_USER=${RABBITMQ_USER} | ||
| - RABBITMQ_PASSWORD=${RABBITMQ_PASSWORD} | ||
| - RABBITMQ_VHOST=${RABBITMQ_VHOST} | ||
| - SECRET_KEY=${SECRET_KEY} | ||
| - AWS_REGION=${AWS_REGION} | ||
| - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} | ||
| - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} | ||
| - AWS_S3_ENDPOINT_URL=http://plane-minio:9000 | ||
| - AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME} | ||
| - USE_MINIO=1 | ||
| depends_on: | ||
| - plane-db | ||
| - plane-redis | ||
|
|
||
| live: | ||
| image: artifacts.plane.so/makeplane/plane-live:latest | ||
| restart: always | ||
|
|
||
| plane-db: | ||
| image: postgres:15.7-alpine | ||
| restart: always | ||
| command: postgres -c 'max_connections=1000' | ||
| volumes: | ||
| - pgdata:/var/lib/postgresql/data | ||
| environment: | ||
| POSTGRES_USER: ${POSTGRES_USER} | ||
| POSTGRES_DB: ${POSTGRES_DB} | ||
| POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} | ||
| PGDATA: /var/lib/postgresql/data | ||
|
|
||
| plane-redis: | ||
| image: valkey/valkey:7.2.11-alpine | ||
| restart: always | ||
| volumes: | ||
| - redisdata:/data | ||
|
|
||
| plane-mq: | ||
| image: rabbitmq:3.13.6-management-alpine | ||
| restart: always | ||
| environment: | ||
| RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER} | ||
| RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD} | ||
| RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST} | ||
| volumes: | ||
| - rabbitmq_data:/var/lib/rabbitmq | ||
|
|
||
| plane-minio: | ||
| image: minio/minio | ||
| restart: always | ||
| command: server /export --console-address ":9090" | ||
| volumes: | ||
| - uploads:/export | ||
| environment: | ||
| MINIO_ROOT_USER: ${AWS_ACCESS_KEY_ID} | ||
| MINIO_ROOT_PASSWORD: ${AWS_SECRET_ACCESS_KEY} | ||
|
|
||
| proxy: | ||
| image: artifacts.plane.so/makeplane/plane-proxy:latest |
There was a problem hiding this comment.
Version pinning recommended for all Docker images.
All services in this compose file use :latest tags, which is not recommended for production deployments. This creates several risks:
- Reproducibility: Deployments at different times may pull different versions
- Stability: Automatic updates may introduce breaking changes
- Rollback difficulty: Hard to revert to a known-good state
Consider adding a note recommending users replace :latest with specific version tags (e.g., v1.2.0 or stable) for all images:
plane-frontend:latestplane-admin:latestplane-space:latestplane-backend:latestplane-live:latestplane-proxy:latest
Infrastructure images (postgres, valkey, rabbitmq, minio) are already pinned, which is good practice.
| SECRET_KEY=<random-50-char-string> | ||
| LIVE_SERVER_SECRET_KEY=<random-string> |
There was a problem hiding this comment.
SECRET_KEY generation guidance needed here too.
Same as the earlier comment on lines 132-133: provide users with instructions for generating cryptographically secure SECRET_KEY values. This is especially important since this section may be read independently of the Docker Compose approach.
🤖 Prompt for AI Agents
In `@deployments/dokploy/DEPLOY.md` around lines 493 - 494, Add explicit guidance
beside the SECRET_KEY and LIVE_SERVER_SECRET_KEY examples: explain they must be
cryptographically secure random strings (suggest length e.g., 50+ chars), show
secure generation commands (for example use openssl rand -base64 50 or Python:
python -c "import secrets; print(secrets.token_urlsafe(50))"), instruct readers
to store them in environment variables or a .env file and never commit them to
source control, and note that LIVE_SERVER_SECRET_KEY should be different from
SECRET_KEY and kept secret for production use; update the text around the
SECRET_KEY and LIVE_SERVER_SECRET_KEY examples accordingly.
Description
This PR adds a comprehensive Vietnamese deployment guide for deploying Plane on Dokploy. The guide covers three different deployment approaches with detailed step-by-step instructions, environment configuration, troubleshooting, and best practices.
The document (
deployments/dokploy/DEPLOY.md) includes:Architecture Overview - Complete service breakdown with ports and descriptions
Three Deployment Methods:
Detailed Configuration:
Operational Guidance:
Type of Change
Key Features
Test Scenarios
This is a documentation-only change. The guide has been structured to be:
References
https://claude.ai/code/session_01CTtRjowgPvFWBCESwRbHRx
Summary by CodeRabbit