Каждый сервисный стек на firefly — это директория /home/compose/<prefix>-<name>/ со строгой структурой. Конвенция отлажена на 14+ стеках (zabbix, gitlab, mail, lo-1c-analytics, www-tenants для разных tenants и т.д.) — отклонение усложняет операции (бэкап-скрипты, мониторинг, миграция между хостами).
/home/compose/<prefix>-<name>/
├── docker/docker-compose.yml # compose, version 3.1, bridge-сеть на стек
├── nginx/<name>.conf # legacy vhost, см. ниже
├── data/ # persistent данные (на самом деле bind-mount /mnt/compose/...)
└── backup/ # снапшоты/архивы (опционально)
Именуют тенанта/проект:
pro-4gain-* — основная 4gain.pro инфраlo-* — LoPlusorg-* — *.org сайтыru-* — *.ru сайтыtech-* — *.tech сайтыДля нового сервиса 4gain ставить префикс pro-4gain-.
Внутри compose volumes писать /mnt/compose/<prefix>-<name>/data/..., а директория проекта живёт в /home/compose/<prefix>-<name>/. /home/compose и /mnt/compose — разные точки, но с одинаковым содержимым (вероятно bind-mount). Использовать /mnt/compose/... в compose-файлах для консистентности с существующими стеками.
Единая точка входа на firefly — traefik в Docker Swarm (контейнер traefik_traefik.1.*, биндит host 80/443). Бэкенд-сервисы из compose-стеков экспонируются на уникальный host-port из произвольного диапазона (видел 70, 72, 81, 83, 84, 86, 87, 89, 5010 и т.п.) и подключаются к traefik через file-provider (/mnt/swarm/traefik_data/custom/<name>.yml).
nginx на хосте не установлен — каталоги nginx/<name>.conf в стеках это либо унаследованный артефакт, либо шаблон для какого-то отдельного nginx-вхождения; для нового стека рассчитывать только на traefik.
Let's Encrypt через traefik resolver letsEncrypt (HTTP-01 challenge на 80/tcp). Серты — в /mnt/swarm/traefik_data/acme.json. Для VPN-only имён (*.vpn.4gain.pro) — resolver letsEncryptDNS (DNS-01 через DigitalOcean провайдера). Подробно — см. Traefik.
Пароли БД, root-пароли, MYSQL_PASSWORD и т.п. идут в открытом виде прямо в docker-compose.yml. Это намеренная конвенция репо (см. также plaintext в inventory/group_vars/all.yml) — не предлагать vault/secret-store для нового стека без явной просьбы.
name: в compose-файлеВ каждом docker-compose.yml на firefly обязательно указывать верхнеуровневый name: <stack-id>:
name: pro-4gain-netbox
services:
netbox:
...
Без этого compose project_name берётся из родительской директории — а так как все стеки лежат в /home/compose/<...>/docker/, project_name для всех становится docker. Операции вроде:
docker compose downdocker compose down --remove-orphansdocker compose up --remove-orphansв одном стеке могут затронуть/удалить контейнеры других стеков потому что compose видит их как orphans с тем же project name.
Также не использовать --remove-orphans в скриптах деплоя на firefly.
Deploy pro-4gain-zabbix снёс docker-mailserver-1 контейнер из стека pro-4gain-mail. Пришлось руками поднимать docker compose up -d в /home/compose/pro-4gain-mail/docker/.
После этого случая в каждый ручной compose-стек был добавлен name: (через down → patch → up):
pro-4gain-mail, pro-4gain-www, ru-nc13-www, org-tatarnikov-www, tgUserStoryReport, lo-1c-analytics, lo-voicebot — патчены, backup'ы как docker-compose.yml.bak-<ts>.tech-estim-www и gitlab — name: уже было.Для нового стека 4gain воспроизводить структуру pro-4gain-zabbix или pro-4gain-netbox 1:1:
docker/docker-compose.yml с name: pro-4gain-<x> в шапкеcontainer_name/mnt/compose/<prefix>-<name>/data/...<name>.yml в /mnt/swarm/traefik_data/custom/Changelog
forgain_compose_convention (claude/forGain)