Docker and Kubernetes Deployment Architecture for Self-Hosting Plane
Plane's self-hosted deployment uses a microservices architecture with five containerized application services (web, admin, space, api, live), three background workers (Celery, beat, migrator), and four infrastructure components (PostgreSQL, Valkey/Redis, RabbitMQ, MinIO), deployable via Docker Compose or the community Helm chart.
The makeplane/plane repository provides complete infrastructure definitions for running the project management platform on your own servers. Whether you choose Docker Compose for single-node deployments or Kubernetes for orchestrated scaling, the Docker and Kubernetes deployment architecture for self-hosting Plane maintains identical service boundaries and environment variable contracts.
Core Application Services
Plane splits its functionality across five distinct application services defined in the root docker-compose.yml. Each service builds from a dedicated Dockerfile in the apps/ directory.
Frontend Services
- web (
apps/web/Dockerfile.web): The main React-based end-user interface serving the project management dashboard on port 80. - admin (
apps/admin/Dockerfile.admin): A separate React administration UI for system-level configuration. - space (
apps/space/Dockerfile.space): The React "Space" UI providing distinct workspace functionality.
Backend Services
- api (
apps/api/Dockerfile.api): The Django REST API handling authentication, business logic, and CRUD operations. All frontend services depend on this component. - live (
apps/live/Dockerfile.live): A WebSocket server that pushes real-time updates to connected clients.
In Docker Compose, these services express startup dependencies using depends_on constraints. The Kubernetes Helm chart translates these into PodAffinity rules ensuring UI pods start only after the API pod reports readiness.
Background Processing Layer
Asynchronous tasks run through Celery workers managed by three distinct deployment patterns:
- worker (
./bin/docker-entrypoint-worker.sh): Standard Celery workers processing async jobs like file uploads and email notifications. In Kubernetes, this maps to aDeploymentwith configurablereplicasfor horizontal scaling. - beat-worker (
./bin/docker-entrypoint-beat.sh): The Celery beat scheduler for periodic tasks (cleanup, analytics). Deployed as a single-replicaDeployment. - migrator (
./bin/docker-entrypoint-migrator.sh): A one-shot database migration job that runs before application startup. In Kubernetes, this implements aJobresource that completes before the main services scale up.
All workers consume environment variables from the same .env file mounted at env_file: - ./apps/api/.env in the Compose configuration.
Data and Infrastructure Stack
Plane requires four stateful infrastructure services for persistence, caching, and messaging:
| Service | Docker Image | Kubernetes Implementation | Purpose |
|---|---|---|---|
| plane-db | postgres:15.7-alpine |
StatefulSet + PersistentVolumeClaim (pgdata) |
Primary relational database for Django models |
| plane-redis | valkey/valkey:7.2.11-alpine |
StatefulSet + PVC (redisdata) |
Caching layer and Celery result backend |
| plane-mq | rabbitmq:3.13.6-management-alpine |
StatefulSet + PVC (rabbitmq_data) |
Message broker for Celery task queues |
| plane-minio | minio/minio |
Deployment + PVC (uploads) |
S3-compatible object storage for file uploads |
| proxy | Custom Nginx (apps/proxy/Dockerfile.ce) |
Deployment + Service |
Reverse proxy and TLS termination |
The infrastructure services reference a top-level .env file (lines 16-22 in docker-compose.yml) for credentials and connection strings. In Kubernetes, these values migrate to ConfigMap or Secret resources mounted as environment variables.
Kubernetes Implementation with Helm
The community Helm chart located in deployments/kubernetes/community packages Plane for production Kubernetes clusters and publishes to Artifact Hub.
Key Kubernetes Mappings
Docker Compose services translate to specific workload controllers:
- Stateless Applications (
web,admin,space,api,live):Deployment+Service(ClusterIP) - Background Workers:
Deploymentwith configurablereplicaCount - Database Migrations:
Job(run-once) - Stateful Services (PostgreSQL, Valkey, RabbitMQ):
StatefulSet+PersistentVolumeClaim
The values.yaml file in the Helm chart mirrors the Docker Compose environment variables, allowing operators to configure POSTGRES_USER, POSTGRES_PASSWORD, AWS_ACCESS_KEY_ID, and other secrets while tuning resource limits and replica counts.
Networking and Ingress
In Docker environments, all containers share a single Docker network with the proxy container exclusively exposing ports 80 and 443. The Kubernetes chart creates a Service of type LoadBalancer (or NodePort for on-premises clusters) for the proxy deployment. An optional Ingress resource enables hostname-based routing to distinct UI services.
Persistence Configuration
Each stateful component mounts specific PVCs that survive pod restarts:
- PostgreSQL mounts
pgdataat/var/lib/postgresql/data - Valkey mounts
redisdataat/data - RabbitMQ mounts
rabbitmq_dataat/var/lib/rabbitmq - MinIO mounts
uploadsat/export
All PVCs specify storageClassName matching the cluster's default storage class.
Architecture Flow and Request Path
Understanding the request flow clarifies how components interact in the Docker and Kubernetes deployment architecture for self-hosting Plane:
- Ingress/Load Balancer receives external HTTPS traffic and routes to the
proxyservice. - Proxy terminates TLS and path-routes requests to
web,admin, orspaceservices based on URL patterns. - UI Services call the
apiservice for authentication, data access, and business logic operations. - API persists data to PostgreSQL, caches in Valkey/Redis, queues tasks to RabbitMQ, and stores files in MinIO.
- Live service subscribes to RabbitMQ topics and pushes real-time updates via WebSockets to connected clients.
- Celery Workers consume background jobs from RabbitMQ (e.g., processing file uploads, sending notifications).
- Beat Worker schedules periodic maintenance tasks like cleanup and analytics aggregation.
Summary
- Plane's architecture consists of five application containers (web, admin, space, api, live), three worker types (Celery, beat, migrator), and four infrastructure services (PostgreSQL 15.7, Valkey 7.2, RabbitMQ 3.13, MinIO).
- The reference implementation uses
docker-compose.ymlat the repository root, while production Kubernetes deployments use the community Helm chart indeployments/kubernetes/community. - Stateful services require
PersistentVolumeClaimswithpgdata,redisdata,rabbitmq_data, anduploadsvolumes to ensure data persistence. - The
proxycontainer (Nginx) handles external traffic, TLS termination, and internal routing to UI and API services. - Environment configuration is unified through
.envfiles in Docker andConfigMap/Secretresources in Kubernetes.
Frequently Asked Questions
What hardware requirements are needed to self-host Plane?
A minimal production deployment requires 4 vCPU cores and 8GB RAM to run the core services, PostgreSQL, and Redis comfortably. The Kubernetes Helm chart allows resource limits to be tuned per-component in values.yaml, while Docker Compose deployments should ensure the host has sufficient resources for all defined services.
How do I scale background workers in the Kubernetes deployment?
Modify the replicaCount value for the plane-worker deployment in the Helm chart's values.yaml file. The worker deployment uses the same apps/api/Dockerfile.api image but executes ./bin/docker-entrypoint-worker.sh to process Celery tasks. Horizontal scaling adds parallel job processing capacity without affecting the beat-worker or migrator jobs.
Can I use external PostgreSQL or Redis instead of the containerized versions?
Yes. Both the Docker Compose file and Helm chart support external data sources. Remove the plane-db and plane-redis service definitions from Docker Compose, or set enabled: false for these components in the Helm values.yaml. Configure the DATABASE_URL and REDIS_URL environment variables to point to your external managed services.
What is the difference between the Docker Compose and Kubernetes networking models?
Docker Compose creates an isolated bridge network where all containers communicate via internal DNS names, with only the proxy service exposing ports 80/443 to the host. Kubernetes uses ClusterIP services for internal communication, optionally exposing the proxy via LoadBalancer or NodePort services, and supports Ingress resources for HTTP/HTTPS routing based on hostnames and path prefixes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →