# #region docker.compose.enterprise-clean [C:4] [TYPE Module] [SEMANTICS docker,compose,enterprise] # @BRIEF Enterprise docker compose — сборка backend + frontend из исходников, # встроенный Postgres (контейнер), корп. сертификаты. # @PRE Docker и docker compose установлены. Стандартный файл .env настроен. # Postgres: запускается в контейнере (сервис db). Для внешнего PG — переопределить POSTGRES_HOST. # Сертификаты: опциональные .crt файлы в CERTS_PATH монтируются в /opt/certs. # @POST Сервисы db, backend и frontend запущены. SSL терминация в nginx опциональна. # @SIDE_EFFECT backend использует ENTRYPOINT для установки сертификатов и bootstrap admin. # frontend автоопределяет наличие SSL сертификатов и переключает nginx конфиг. # @LAYER Infrastructure # @RELATION DEPENDS_ON -> [docker/backend.Dockerfile] # @RELATION DEPENDS_ON -> [docker/frontend.Dockerfile] # @RELATION DEPENDS_ON -> [docker/nginx.conf] # @RELATION DEPENDS_ON -> [docker/nginx.ssl.conf] # @RELATION DEPENDS_ON -> [docker/frontend.entrypoint.sh] # @RELATION DEPENDS_ON -> [docker/backend.entrypoint.sh] # @DATA_CONTRACT Input: .env + ./certs/*.crt -> Output: запущенные контейнеры # @INVARIANT При использовании встроенного postgres (сервис db) healthcheck гарантирует # готовность БД через depends_on condition: service_healthy. # Для внешнего PG — переопределить POSTGRES_HOST и удалить сервис db. # @INVARIANT Если CERTS_PATH пуст или не содержит .crt файлов, entrypoint не падает. # @INVARIANT nginx слушает порт 80 всегда. Порт 443 включается только если есть server.crt + server.key. # @RATIONALE Встроенный postgres-container упрощает развёртывание: не требует внешнего # PG-сервер. Для корпоративных сред можно переопределить POSTGRES_HOST на внешний адрес # и удалить сервис db — compose остаётся гибким. # @RATIONALE Build из исходников вместо pre-built images: предприятие контролирует версии кода # и может патчить зависимости. Не подходит для air-gapped — для этого есть bundle:light. # @REJECTED Использование `image:` + `pull_policy: never` отвергнуто — не работает для сборки # из исходников на целевой машине. Гибридный `build: + image:` тоже отвергнут — усложняет # логику build.sh и сбивает с толку оператора. services: db: image: ${POSTGRES_IMAGE:-postgres:16-alpine} restart: unless-stopped # Compatibility workaround for legacy Docker/libseccomp hosts running PostgreSQL 16. security_opt: - seccomp=unconfined environment: POSTGRES_DB: ${POSTGRES_DB:-ss_tools} POSTGRES_USER: ${POSTGRES_USER:-postgres} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env} ports: - "${POSTGRES_HOST_PORT:-5432}:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-ss_tools}"] interval: 10s timeout: 5s retries: 10 backend: build: context: . dockerfile: docker/backend.Dockerfile restart: unless-stopped depends_on: db: condition: service_healthy environment: DATABASE_URL: postgresql+psycopg2://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}@${POSTGRES_HOST:-db}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-ss_tools} STORAGE_ROOT_PATH: /app/storage DB_SCHEMA: ${DB_SCHEMA:-public} # One-shot destructive reset, only for databases NOT on the current chain # (legacy/orphaned Alembic revisions). Chain-managed schemas are never wiped. # The reset drops schema objects, so it needs object ownership, not schema ownership. RESET_DATABASE_SCHEMA: ${RESET_DATABASE_SCHEMA:-true} BACKEND_PORT: 8000 ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-} MCP_ALLOWED_HOSTS: ${MCP_ALLOWED_HOSTS:-127.0.0.1:*,localhost:*,[::1]:*} MCP_ALLOWED_ORIGINS: ${MCP_ALLOWED_ORIGINS:-http://127.0.0.1:*,http://localhost:*,http://[::1]:*} FORWARDED_ALLOW_IPS: ${FORWARDED_ALLOW_IPS:-*} SERVICE_JWT: ${SERVICE_JWT:?Set SERVICE_JWT in .env} AUTH_SECRET_KEY: ${AUTH_SECRET_KEY:?Set AUTH_SECRET_KEY in .env} ENCRYPTION_KEY: ${ENCRYPTION_KEY:?ENCRYPTION_KEY обязателен — сгенерируйте и укажите в .env} ENABLE_BELIEF_STATE_LOGGING: ${ENABLE_BELIEF_STATE_LOGGING:-true} TASK_LOG_LEVEL: ${TASK_LOG_LEVEL:-INFO} INITIAL_ADMIN_CREATE: ${INITIAL_ADMIN_CREATE:-false} INITIAL_ADMIN_USERNAME: ${INITIAL_ADMIN_USERNAME:-admin} INITIAL_ADMIN_PASSWORD: ${INITIAL_ADMIN_PASSWORD:-} INITIAL_ADMIN_EMAIL: ${INITIAL_ADMIN_EMAIL:-} OPENAI_API_KEY: ${OPENAI_API_KEY:-} ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} FEATURES__DATASET_REVIEW: ${FEATURES__DATASET_REVIEW:-true} FEATURES__HEALTH_MONITOR: ${FEATURES__HEALTH_MONITOR:-true} LLM_CA_CERT_URLS: ${LLM_CA_CERT_URLS:-} # Путь до сертификатов внутри контейнера — всегда /opt/certs CERTS_PATH: /opt/certs ports: - "127.0.0.1:${BACKEND_HOST_PORT:-8001}:8000" volumes: # Единая точка хранения: бэкапы → /app/storage/backups/, git-repos → /app/storage/repositories/, LLM-скриншоты → /app/storage/screenshots/ - ./storage:/app/storage # Корпоративные CA-сертификаты (.crt файлы). Монтируются в /opt/certs, # entrypoint.sh установит их в системное хранилище доверия. - ${CERTS_PATH:-./certs}:/opt/certs:ro frontend: build: context: . dockerfile: docker/frontend.Dockerfile restart: unless-stopped depends_on: - backend environment: # Пароль от приватного ключа/PKCS#12 для SSL терминации nginx. # Опционально: если server.key не зашифрован или используется HTTP — не требуется. SSL_KEY_PASSPHRASE: ${SSL_KEY_PASSPHRASE:-} ports: - "${FRONTEND_HOST_PORT:-8000}:80" # Если в CERTS_PATH есть server.crt + server.key — nginx включит HTTPS на 443. # Если cert-файлов нет — порт 443 не открывается, entrypoint использует HTTP-only конфиг. - "${FRONTEND_SSL_PORT:-443}:443" volumes: # Для frontend тоже можно смонтировать сертификаты — nginx entrypoint # автоматически установит CA-сертификаты в Alpine и переключит SSL конфиг. - ${CERTS_PATH:-./certs}:/opt/certs:ro volumes: postgres_data: # #endregion docker.compose.enterprise-clean