mirror of
https://github.com/runyanjake/olomana.git
synced 2026-06-25 08:04:52 -07:00
300 lines
9.8 KiB
YAML
300 lines
9.8 KiB
YAML
networks:
|
||
traefik:
|
||
external: true
|
||
plane:
|
||
driver: bridge
|
||
|
||
# Shared environment for all plane-backend services
|
||
x-backend-env:
|
||
&backend-env
|
||
SECRET_KEY: ${SECRET_KEY}
|
||
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@plane-db/${POSTGRES_DB}
|
||
REDIS_URL: redis://plane-redis:6379/
|
||
AMQP_URL: amqp://${RABBITMQ_USER}:${RABBITMQ_PASSWORD}@plane-mq:5672/
|
||
WEB_URL: https://${DOMAIN}
|
||
CORS_ALLOWED_ORIGINS: https://${DOMAIN}
|
||
DOCKERIZED: 1
|
||
GUNICORN_WORKERS: ${GUNICORN_WORKERS:-2}
|
||
USE_MINIO: 1
|
||
AWS_REGION: us-east-1
|
||
AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER}
|
||
AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD}
|
||
AWS_S3_ENDPOINT_URL: http://plane-minio:9000
|
||
AWS_S3_BUCKET_NAME: ${MINIO_BUCKET_NAME:-uploads}
|
||
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
|
||
|
||
services:
|
||
|
||
# ── Database ─────────────────────────────────────────────────────────────────
|
||
|
||
plane-db:
|
||
image: postgres:15.7-alpine
|
||
container_name: plane-db
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
environment:
|
||
POSTGRES_DB: ${POSTGRES_DB}
|
||
POSTGRES_USER: ${POSTGRES_USER}
|
||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||
PGDATA: /var/lib/postgresql/data
|
||
volumes:
|
||
- /pwspool/software/plane/db:/var/lib/postgresql/data
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
|
||
interval: 5s
|
||
timeout: 5s
|
||
retries: 5
|
||
|
||
# ── Cache ─────────────────────────────────────────────────────────────────────
|
||
|
||
plane-redis:
|
||
image: valkey/valkey:7.2.11-alpine
|
||
container_name: plane-redis
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
volumes:
|
||
- /pwspool/software/plane/redis:/data
|
||
healthcheck:
|
||
test: ["CMD-SHELL", "redis-cli ping"]
|
||
interval: 5s
|
||
timeout: 5s
|
||
retries: 5
|
||
|
||
# ── Message Queue ─────────────────────────────────────────────────────────────
|
||
|
||
plane-mq:
|
||
image: rabbitmq:3.13.6-management-alpine
|
||
container_name: plane-mq
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
environment:
|
||
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER}
|
||
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD}
|
||
RABBITMQ_DEFAULT_VHOST: /
|
||
volumes:
|
||
- /pwspool/software/plane/rabbitmq:/var/lib/rabbitmq
|
||
healthcheck:
|
||
test: ["CMD", "rabbitmq-diagnostics", "check_running", "-q"]
|
||
interval: 30s
|
||
timeout: 10s
|
||
retries: 5
|
||
|
||
# ── Object Storage (MinIO) ────────────────────────────────────────────────────
|
||
|
||
plane-minio:
|
||
image: minio/minio:latest
|
||
container_name: plane-minio
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
command: server /export --console-address ":9090"
|
||
environment:
|
||
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||
volumes:
|
||
- /pwspool/software/plane/minio:/export
|
||
healthcheck:
|
||
test: ["CMD", "mc", "ready", "local"]
|
||
interval: 30s
|
||
timeout: 20s
|
||
retries: 3
|
||
|
||
plane-createbuckets:
|
||
image: minio/mc:latest
|
||
container_name: plane-createbuckets
|
||
restart: "no"
|
||
networks:
|
||
- plane
|
||
environment:
|
||
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||
MINIO_BUCKET_NAME: ${MINIO_BUCKET_NAME:-uploads}
|
||
depends_on:
|
||
plane-minio:
|
||
condition: service_healthy
|
||
entrypoint: >
|
||
/bin/sh -c "
|
||
mc alias set myminio http://plane-minio:9000 $$MINIO_ROOT_USER $$MINIO_ROOT_PASSWORD &&
|
||
mc mb myminio/$$MINIO_BUCKET_NAME --ignore-existing"
|
||
|
||
# ── Migrations (one-shot) ─────────────────────────────────────────────────────
|
||
|
||
migrator:
|
||
image: makeplane/plane-backend:${APP_RELEASE:-stable}
|
||
container_name: plane-migrator
|
||
restart: "no"
|
||
networks:
|
||
- plane
|
||
command: ./bin/docker-entrypoint-migrator.sh
|
||
environment:
|
||
<<: *backend-env
|
||
depends_on:
|
||
plane-db:
|
||
condition: service_healthy
|
||
plane-redis:
|
||
condition: service_healthy
|
||
|
||
# ── API ───────────────────────────────────────────────────────────────────────
|
||
|
||
api:
|
||
image: makeplane/plane-backend:${APP_RELEASE:-stable}
|
||
container_name: plane-api
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
command: ./bin/docker-entrypoint-api.sh
|
||
environment:
|
||
<<: *backend-env
|
||
volumes:
|
||
- /pwspool/software/plane/logs/api:/logs
|
||
depends_on:
|
||
plane-db:
|
||
condition: service_healthy
|
||
plane-redis:
|
||
condition: service_healthy
|
||
plane-mq:
|
||
condition: service_healthy
|
||
migrator:
|
||
condition: service_completed_successfully
|
||
|
||
# ── Celery Worker ─────────────────────────────────────────────────────────────
|
||
|
||
worker:
|
||
image: makeplane/plane-backend:${APP_RELEASE:-stable}
|
||
container_name: plane-worker
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
command: ./bin/docker-entrypoint-worker.sh
|
||
environment:
|
||
<<: *backend-env
|
||
volumes:
|
||
- /pwspool/software/plane/logs/worker:/logs
|
||
depends_on:
|
||
plane-db:
|
||
condition: service_healthy
|
||
plane-redis:
|
||
condition: service_healthy
|
||
plane-mq:
|
||
condition: service_healthy
|
||
migrator:
|
||
condition: service_completed_successfully
|
||
|
||
# ── Celery Beat ───────────────────────────────────────────────────────────────
|
||
|
||
beat-worker:
|
||
image: makeplane/plane-backend:${APP_RELEASE:-stable}
|
||
container_name: plane-beat-worker
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
command: ./bin/docker-entrypoint-beat.sh
|
||
environment:
|
||
<<: *backend-env
|
||
volumes:
|
||
- /pwspool/software/plane/logs/beat:/logs
|
||
depends_on:
|
||
plane-db:
|
||
condition: service_healthy
|
||
plane-redis:
|
||
condition: service_healthy
|
||
plane-mq:
|
||
condition: service_healthy
|
||
migrator:
|
||
condition: service_completed_successfully
|
||
|
||
# ── Frontend ──────────────────────────────────────────────────────────────────
|
||
|
||
web:
|
||
image: makeplane/plane-frontend:${APP_RELEASE:-stable}
|
||
container_name: plane-web
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
environment:
|
||
NEXT_PUBLIC_API_BASE_URL: https://${DOMAIN}
|
||
NEXT_PUBLIC_SPACE_BASE_URL: https://${DOMAIN}/spaces
|
||
NEXT_PUBLIC_ADMIN_BASE_URL: https://${DOMAIN}/god-mode
|
||
NEXT_PUBLIC_LIVE_BASE_URL: https://${DOMAIN}/live
|
||
depends_on:
|
||
- api
|
||
|
||
# ── Admin Dashboard ───────────────────────────────────────────────────────────
|
||
|
||
admin:
|
||
image: makeplane/plane-admin:${APP_RELEASE:-stable}
|
||
container_name: plane-admin
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
environment:
|
||
NEXT_PUBLIC_API_BASE_URL: https://${DOMAIN}
|
||
NEXT_PUBLIC_ADMIN_BASE_URL: https://${DOMAIN}/god-mode
|
||
depends_on:
|
||
- api
|
||
|
||
# ── Public Space ──────────────────────────────────────────────────────────────
|
||
|
||
space:
|
||
image: makeplane/plane-space:${APP_RELEASE:-stable}
|
||
container_name: plane-space
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
environment:
|
||
NEXT_PUBLIC_API_BASE_URL: https://${DOMAIN}
|
||
NEXT_PUBLIC_SPACE_BASE_URL: https://${DOMAIN}/spaces
|
||
depends_on:
|
||
- api
|
||
|
||
# ── Live (real-time collaboration) ────────────────────────────────────────────
|
||
|
||
live:
|
||
image: makeplane/plane-live:${APP_RELEASE:-stable}
|
||
container_name: plane-live
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
environment:
|
||
LIVE_BASE_PATH: /live
|
||
SECRET_KEY: ${SECRET_KEY}
|
||
API_BASE_URL: http://api:8000
|
||
depends_on:
|
||
- api
|
||
|
||
# ── Proxy (gateway – only service on the Traefik network) ─────────────────────
|
||
|
||
proxy:
|
||
image: makeplane/plane-proxy:${APP_RELEASE:-stable}
|
||
container_name: plane-proxy
|
||
restart: always
|
||
networks:
|
||
- plane
|
||
- traefik
|
||
environment:
|
||
# plane-proxy is Caddy — it needs SITE_ADDRESS (listen spec),
|
||
# BUCKET_NAME, and FILE_SIZE_LIMIT. Traefik terminates TLS in front
|
||
# of it, so Caddy listens plain-HTTP on :80 and issues no certs.
|
||
SITE_ADDRESS: ":80"
|
||
BUCKET_NAME: ${MINIO_BUCKET_NAME:-uploads}
|
||
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
|
||
CERT_EMAIL: ""
|
||
CERT_ACME_DNS: ""
|
||
TRUSTED_PROXIES: "0.0.0.0/0"
|
||
depends_on:
|
||
- web
|
||
- api
|
||
- admin
|
||
- space
|
||
- live
|
||
labels:
|
||
- traefik.enable=true
|
||
- traefik.http.routers.plane.rule=Host(`${DOMAIN}`)
|
||
- traefik.http.routers.plane.tls=true
|
||
- traefik.http.routers.plane.tls.certresolver=lets-encrypt
|
||
- traefik.http.services.plane.loadbalancer.server.port=80
|
||
- traefik.docker.network=traefik
|