services: k3s-server: image: rancher/k3s:v1.36.2-k3s1 container_name: k3s-server command: - server - --tls-san=127.0.0.1 - --tls-san=k3s-server - --tls-san=${K3S_API_HOST:-127.0.0.1} # внешний IP/домен для доступа к apiserver извне - --disable=traefik privileged: true cgroup: host # kubelet в cgroup v2 (Ubuntu 22.04+/RedOS) restart: unless-stopped environment: K3S_TOKEN: ${K3S_TOKEN:-supersecrettoken} K3S_KUBECONFIG_OUTPUT: /output/kubeconfig.yaml K3S_KUBECONFIG_MODE: "644" ports: - "6443:6443" # kube-apiserver — доступен извне; ОБЯЗАТЕЛЬНО ограничь фаерволом до доверенных IP - "80:80" # ingress http — задействуются после установки ingress-контроллера - "443:443" # ingress https volumes: - k3s-server-data:/var/lib/rancher/k3s # etcd/state, образы, манифесты — только named volume - ./k3s:/output:z # отсюда забираем контекст k8s (:z — SELinux label для RedOS) tmpfs: - /run - /var/run ulimits: nproc: 65535 nofile: soft: 65535 hard: 65535 healthcheck: test: ["CMD", "kubectl", "get", "--raw=/readyz"] interval: 10s timeout: 5s retries: 30 start_period: 30s k3s-worker: image: rancher/k3s:v1.36.2-k3s1 container_name: k3s-worker command: - agent privileged: true cgroup: host # kubelet в cgroup v2 (Ubuntu 22.04+/RedOS) restart: unless-stopped depends_on: k3s-server: condition: service_healthy environment: K3S_URL: https://k3s-server:6443 K3S_TOKEN: ${K3S_TOKEN:-supersecrettoken} volumes: - k3s-worker-data:/var/lib/rancher/k3s tmpfs: - /run - /var/run ulimits: nproc: 65535 nofile: soft: 65535 hard: 65535 gitea: image: gitea/gitea:1.22 container_name: gitea restart: unless-stopped environment: USER_UID: 1000 USER_GID: 1000 GITEA__server__ROOT_URL: ${GITEA_ROOT_URL:-http://localhost:3000/} GITEA__server__SSH_PORT: ${GITEA_SSH_PORT:-2222} ports: - "3000:3000" # web UI (80/443 заняты k3s) - "${GITEA_SSH_PORT:-2222}:22" # git over ssh volumes: - ./gitea-data:/data:z # :z — SELinux label для RedOS healthcheck: test: ["CMD", "curl", "-fsS", "http://localhost:3000/api/healthz"] interval: 10s timeout: 5s retries: 12 start_period: 20s # --------------------------------------------------------------------------- # Инфраструктурные зависимости apps/django (sarex-backend). # Django деплоится в k3s и ходит сюда — про связность k3s→compose см. README. # Креды/версии взяты из sarex-backend/docker-compose.yaml и apps/django/.env.example. # --------------------------------------------------------------------------- postgres: image: postgres:12-alpine container_name: postgres restart: unless-stopped environment: POSTGRES_DB: ${SAREX_POSTGRES_DB:-sarex_db} POSTGRES_USER: ${SAREX_POSTGRES_USER:-sarex} POSTGRES_PASSWORD: ${SAREX_POSTGRES_PASSWORD:-sarex} ports: - "5432:5432" volumes: - sarex-postgres-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${SAREX_POSTGRES_USER:-sarex} -d ${SAREX_POSTGRES_DB:-sarex_db}"] interval: 10s timeout: 5s retries: 12 start_period: 10s redis: image: redis:7-alpine container_name: redis restart: unless-stopped command: ["redis-server", "--save", "60", "1", "--loglevel", "warning"] ports: - "6379:6379" volumes: - sarex-redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 12 start_period: 5s rabbitmq: image: bitnami/rabbitmq:3.11.23 container_name: rabbitmq restart: unless-stopped environment: RABBITMQ_VHOST: ${SAREX_RABBITMQ_VHOST:-api} RABBITMQ_USERNAME: ${SAREX_RABBITMQ_USER:-rabbit} RABBITMQ_PASSWORD: ${SAREX_RABBITMQ_PASSWORD:-rabbit} RABBITMQ_DISK_FREE_ABSOLUTE_LIMIT: 200MB ports: - "5672:5672" # AMQP - "15672:15672" # management UI volumes: - sarex-rabbitmq-data:/bitnami/rabbitmq/mnesia healthcheck: test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] interval: 15s timeout: 10s retries: 12 start_period: 30s minio: image: minio/minio:latest container_name: minio restart: unless-stopped command: ["server", "/data", "--console-address", ":9001"] environment: MINIO_ROOT_USER: ${SAREX_MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${SAREX_MINIO_ROOT_PASSWORD:-minioadmin} ports: - "9000:9000" # S3 API - "9001:9001" # web console volumes: - sarex-minio-data:/data # Одноразовый init: ждёт MinIO и создаёт бакет sarex-media-storage minio-init: image: minio/mc:latest depends_on: - minio entrypoint: - /bin/sh - -c - | until mc alias set local http://minio:9000 "$$MINIO_ROOT_USER" "$$MINIO_ROOT_PASSWORD"; do echo 'waiting for minio...'; sleep 2; done mc mb -p "local/$$MINIO_BUCKET" echo "bucket $$MINIO_BUCKET ready" environment: MINIO_ROOT_USER: ${SAREX_MINIO_ROOT_USER:-minioadmin} MINIO_ROOT_PASSWORD: ${SAREX_MINIO_ROOT_PASSWORD:-minioadmin} MINIO_BUCKET: ${SAREX_MINIO_BUCKET:-sarex-media-storage} restart: "no" # --------------------------------------------------------------------------- # Приложение sarex (backend + celery + frontend). # Образы приватные (cr.yandex) — нужен `docker login cr.yandex`. # Для локальной сборки backend раскомментируй build (репозиторий — соседний). # --------------------------------------------------------------------------- backend: image: ${SAREX_BACKEND_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/sarex-backend-dev:latest} # build: # context: ../../generic/sarex-backend # dockerfile: Dockerfile container_name: sarex-backend restart: unless-stopped environment: &sarex-backend-env ALLOWED_HOSTS: "*" DJANGO_SETTINGS_MODULE: config.settings.production JWT_PRIVATE_KEY: "JWT" JWT_PUBLIC_KEY: "JPK" DJANGO_POSTGRES_HOST: postgres DJANGO_POSTGRES_DATABASE: ${SAREX_POSTGRES_DB:-sarex_db} DJANGO_POSTGRES_USER: ${SAREX_POSTGRES_USER:-sarex} DJANGO_POSTGRES_PASSWORD: ${SAREX_POSTGRES_PASSWORD:-sarex} DJANGO_REDIS_HOST: redis DJANGO_RABBIT_HOSTNAME: rabbitmq DJANGO_RABBIT_USER: ${SAREX_RABBITMQ_USER:-rabbit} DJANGO_RABBIT_PASS: ${SAREX_RABBITMQ_PASSWORD:-rabbit} DJANGO_RABBIT_VHOST: ${SAREX_RABBITMQ_VHOST:-api} # S3 / объектное хранилище → MinIO (сервис minio) S3_HOST: http://minio:9000 AWS_S3_ENDPOINT_URL: http://minio:9000 S3_LOGIN: ${SAREX_MINIO_ROOT_USER:-minioadmin} S3_PASSWORD: ${SAREX_MINIO_ROOT_PASSWORD:-minioadmin} S3_BUCKET: ${SAREX_MINIO_BUCKET:-sarex-media-storage} S3_REGION: ${SAREX_MINIO_REGION:-us-east-1} tty: true ports: - "8000:8000" # HTTP API (uWSGI), migrate выполняется в entrypoint depends_on: postgres: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy minio-init: condition: service_completed_successfully celery: image: ${SAREX_BACKEND_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/sarex-backend-dev:latest} container_name: sarex-celery restart: unless-stopped entrypoint: celery -A config worker -l info -E -Q default -n default_worker.%h --concurrency=1 -B environment: <<: *sarex-backend-env depends_on: postgres: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy minio-init: condition: service_completed_successfully frontend: image: ${SAREX_FRONTEND_IMAGE:-cr.yandex/crp3ccidau046kdj8g9q/sarex-frontend-dev:latest} container_name: sarex-frontend restart: unless-stopped ports: - "8080:80" # web UI depends_on: - backend # Верхний reverse-proxy: единая точка входа → backend / frontend / minio nginx: image: nginx:1.27-alpine container_name: sarex-nginx restart: unless-stopped ports: - "9080:80" # 80/443 заняты k3s volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro,z # :z — SELinux label для RedOS depends_on: - backend - frontend - minio healthcheck: test: ["CMD", "wget", "-qO-", "http://localhost/healthz"] interval: 10s timeout: 5s retries: 6 start_period: 10s volumes: k3s-server-data: k3s-worker-data: gitea-data: sarex-postgres-data: sarex-redis-data: sarex-rabbitmq-data: sarex-minio-data: