# Продакшен-развёртывание (docs/install-guide.md). Образы собираются на сервере из клонированного репозитория. # Перед первым запуском: sudo ./install.sh. Установка / обновление: ./update.sh [vX.Y.Z] name: pipu x-version: &version VERSION: ${PIPU_VERSION:-0.0.0-dev} x-build-rec: &build-rec context: .. dockerfile: services/recommender/Dockerfile args: *version x-library-ro: &library-ro type: bind source: ${PIPU_DATA:-/srv/pipu}/library target: /library read_only: true bind: { propagation: rslave } # Локальная музыка (источники type=local): каталог хоста, например смонтированный диск /mnt/music. # Всем сервисам — только чтение; на запись (импорт загрузок) его видит только storage-agent — /library-host-rw # (docs/library-and-storage.md#запись-в-хранилище). # rslave: диск, смонтированный на хосте уже после старта контейнеров, становится виден внутри без перезапуска. x-library-host-ro: &library-host-ro type: bind source: ${LIBRARY_HOST:-${PIPU_DATA:-/srv/pipu}/library-host} target: /library-host read_only: true bind: { propagation: rslave } x-restart: &restart restart: unless-stopped services: nginx: <<: *restart image: pipu-music-web:${PIPU_VERSION:-dev} build: context: .. dockerfile: apps/web/Dockerfile args: *version ports: ["${HTTP_PORT:-80}:80"] volumes: - *library-ro - *library-host-ro - ${PIPU_DATA:-/srv/pipu}/cache:/cache:ro - ${PIPU_DATA:-/srv/pipu}/uploads:/uploads:ro depends_on: [api] api: <<: *restart image: pipu-music-api:${PIPU_VERSION:-dev} build: context: .. dockerfile: services/api/Dockerfile target: api args: *version env_file: .env environment: &db-env DATABASE_URL: postgres://pipu:${POSTGRES_PASSWORD:?заполните POSTGRES_PASSWORD в .env (sudo ./install.sh)}@postgres:5432/pipu?sslmode=disable volumes: - *library-ro - *library-host-ro - ${PIPU_DATA:-/srv/pipu}/cache:/cache - ${PIPU_DATA:-/srv/pipu}/updates:/updates - ${PIPU_DATA:-/srv/pipu}/uploads:/uploads depends_on: postgres: { condition: service_healthy } redis: { condition: service_started } storage-agent: { condition: service_started } storage-agent: <<: *restart image: pipu-music-storage-agent:${PIPU_VERSION:-dev} build: context: .. dockerfile: services/api/Dockerfile target: storage-agent args: *version cap_add: [SYS_ADMIN] security_opt: ["apparmor:unconfined"] environment: INTERNAL_TOKEN: ${INTERNAL_TOKEN:?заполните INTERNAL_TOKEN в .env (sudo ./install.sh)} LIBRARY_ROOT: /library # rw-точки NFS-хранилищ с приёмом загрузок — каталог внутри контейнера, наружу не виден. LIBRARY_RW_ROOT: /library-rw LIBRARY_HOST_RW_ROOT: /library-host-rw UPLOADS_ROOT: /uploads PIPU_FILE_UID: ${PIPU_FILE_UID:--1} PIPU_FILE_GID: ${PIPU_FILE_GID:--1} LOG_LEVEL: ${LOG_LEVEL:-info} volumes: - type: bind source: ${PIPU_DATA:-/srv/pipu}/library target: /library bind: { propagation: rshared } - *library-host-ro - type: bind source: ${LIBRARY_HOST:-${PIPU_DATA:-/srv/pipu}/library-host} target: /library-host-rw bind: { propagation: rslave } - ${PIPU_DATA:-/srv/pipu}/uploads:/uploads:ro recommender: <<: *restart image: pipu-music-recommender:${PIPU_VERSION:-dev} build: *build-rec command: ["serve"] # только нужные переменные, а не весь .env с секретами Meilisearch и Gitea environment: <<: *db-env REDIS_URL: ${REDIS_URL:-redis://redis:6379/0} INTERNAL_TOKEN: ${INTERNAL_TOKEN:?заполните INTERNAL_TOKEN в .env (sudo ./install.sh)} LOG_LEVEL: ${LOG_LEVEL:-info} depends_on: postgres: { condition: service_healthy } analyzer: <<: *restart image: pipu-music-recommender:${PIPU_VERSION:-dev} build: *build-rec command: ["analyze", "--workers", "4"] environment: <<: *db-env REDIS_URL: ${REDIS_URL:-redis://redis:6379/0} LOG_LEVEL: ${LOG_LEVEL:-info} volumes: - *library-ro - *library-host-ro - ${PIPU_DATA:-/srv/pipu}/models:/models deploy: { resources: { limits: { cpus: "4" } } } depends_on: postgres: { condition: service_healthy } postgres: <<: *restart image: pgvector/pgvector:0.8.7-pg17 environment: POSTGRES_USER: pipu POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: pipu volumes: [ "${PIPU_DATA:-/srv/pipu}/postgres:/var/lib/postgresql/data" ] healthcheck: test: ["CMD-SHELL", "pg_isready -U pipu -d pipu"] interval: 5s retries: 20 redis: <<: *restart image: redis:7.4-alpine command: ["redis-server", "--appendonly", "yes"] volumes: [ "${PIPU_DATA:-/srv/pipu}/redis:/data" ] meilisearch: <<: *restart image: getmeili/meilisearch:v1.11 environment: MEILI_MASTER_KEY: ${MEILI_MASTER_KEY} MEILI_ENV: production volumes: [ "${PIPU_DATA:-/srv/pipu}/meili:/meili_data" ]