🐳 Полное Руководство по Деплою через Docker Compose
Пошаговая инструкция по развертыванию всех 10 сервисов экосистемы Loomix на едином VPS с максимальной безопасностью, отказоустойчивостью и стабильностью.
1. Требования к Серверу (Prerequisites)
Перед началом подготовьте VPS с операционной системой Ubuntu 22.04 LTS или 24.04 LTS:
- Минимум RAM: 4 ГБ физической памяти с минимум 4 ГБ Swap (для быстрых сборок рекомендуется 8 ГБ RAM).
- Процессор: Минимум 2 ядра vCPU (для быстрой сборки Docker-образов рекомендуется 4 vCPU).
Права на Docker Сокет
Docker и Docker Compose должны быть установлены, а текущий пользователь добавлен в группу docker.
sudo usermod -aG docker $USERnewgrp docker # or log out and SSH back indocker ps # should work without sudo2. Перенос Исходного Кода на Сервер
Перенести проект на ваш VPS можно одним из двух удобных способов:
Способ 1: Прямое Клонирование через Git (Рекомендуется)
Храните Переменные Окружения в Безопасности
git clone https://github.com/<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.gitcd <YOUR_REPOSITORY_NAME>Клонирование Приватного Репозитория по SSH-Ключам
- 1. Сгенерируйте пару SSH-ключей на сервере: ssh-keygen -t ed25519
- 2. Выведите и скопируйте публичный ключ: cat ~/.ssh/id_ed25519.pub
- 3. Добавьте этот ключ в раздел Deploy Keys вашего репозитория на GitHub.
- 4. Склонируйте репозиторий по SSH напрямую.
git clone git@github.com:<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.gitcd <YOUR_REPOSITORY_NAME>Клонирование через Personal Access Token (PAT)
git clone https://<YOUR_GITHUB_USERNAME>:<PERSONAL_ACCESS_TOKEN>@github.com/<YOUR_GITHUB_USERNAME>/<YOUR_REPOSITORY_NAME>.gitcd <YOUR_REPOSITORY_NAME>Способ 2: Загрузка Архива (ZIP / Tarball)
Если вы скачали архив с кодом, загрузите его на сервер через scp или rsync:
rsync -avz --exclude 'node_modules' --exclude '.git' --exclude '.next' ./ user@your_vps_ip:/root/next-strapi-medusa3. Мастер Автоматической Настройки (Quick Wizard)
Чтобы установка заняла считанные минуты, мы создали скрипт server-setup.sh, который настраивает Swap, проверяет порты и запускает контейнеры:
chmod +x server-setup.shbash server-setup.shСовет Эксперта:
4. Выбор Профиля Развертывания (Deployment Profiles)
Система поддерживает 3 профиля развертывания под разные сценарии использования:
Нужен ли Собственный Домен?
Запускает все 10 сервисов на одном VPS с поддоменами и автоматическими SSL-сертификатами через Caddy.
Шаги Настройки Профиля B:
- 1. Направьте DNS A-записи домена на IP-адрес вашего сервера.
- 2. Выберите Профиль B при запуске скрипта server-setup.sh.
- 3. Введите ваш основной домен (напр. vashdomen.ru).
- 4. Caddy автоматически получит SSL-сертификаты для всех сервисов.
- 5. Все панели управления сразу готовы к работе по защищенному протоколу HTTPS.
# Profile B: VM / LAN HTTPS (.local hostnames) - Recommended ★ STOREFRONT_PUBLIC_URL=https://store.localMEDUSA_BACKEND_PUBLIC_URL=https://api.localSTRAPI_PUBLIC_URL=https://admin.localMEILISEARCH_PUBLIC_URL=https://search.localMINIO_PUBLIC_URL=https://api.local/minio/mystoreGOOGLE_CALLBACK_URL=https://store.local/ir/account/auth/callback STOREFRONT_URL=http://storefront:8000MEDUSA_NODE_ENV=productionMEDUSA_ALLOW_HTTP_COOKIES=falseCLOUDFLARE_TUNNEL_TOKEN=• Витрина:
https://vashdomen.ru• Medusa:
https://api.vashdomen.ru/app• Strapi:
https://admin.vashdomen.ru/admin• Umami:
https://analytics.vashdomen.ru• OpenObserve:
https://monitor.vashdomen.ruРуководство по Защите в Cloudflare Edge
Перед Делегированием DNS в Cloudflare:
Во избежание бесконечных редиректов (Redirect Loops) установите режим SSL в Cloudflare на Full (Strict).
2. После запуска сервисов (Настройка безопасности после развертывания):
• Режим шифрования SSL/TLS: Установите в Full (Strict).
• Сертификаты Edge: Включите Always Use HTTPS, Automatic HTTPS Rewrites и задайте минимальную версию TLS TLS 1.2 (или 1.3).
• Проксирование DNS: Переведите все DNS-записи в статус с оранжевым облаком (Proxied) для ускорения через CDN и защиты от DDoS-атак на сервер источника.
• Безопасность / WAF: Включите Bot Fight Mode.
• Сеть: Убедитесь, что WebSockets и gRPC включены.
• Кэширование: В разделе Caching > Configuration проверьте, чтобы Browser Cache TTL стоял в значении Respect Existing Headers для сохранения мгновенного обновления корзины и остатков товаров.
HTTP Basic Auth и защита периметра с Caddy:
• Панель администратора Strapi (admin.yourdomain.com/admin* и /): Защищена с помощью HTTP Basic Auth для предотвращения брутфорс-атак. Публичные маршруты API (/api/*) и медиафайлы (/uploads/*) остаются открытыми, чтобы Storefront и Medusa могли обращаться к данным без ошибок 401.
• Панель OpenObserve (monitor.yourdomain.com): Защищена HTTP Basic Auth как второй рубеж защиты в дополнение к внутренним учетным записям OpenObserve.
Сгенерируйте надежный хэш bcrypt для переменной BASIC_AUTH_HASH в .env:
docker run --rm caddy:latest caddy hash-password --plaintext "your_secret_password"Матрица Адресов и Портов по Профилям
| Сервис | Профиль A (Локально) | Профиль B (Один VPS) | Профиль C (Корпоративный) |
|---|---|---|---|
| Витрина Next.js | http://<VM_IP>:8000 | https://store.local | https://yourdomain.com |
| Бэкенд Medusa | http://<VM_IP>:9000/app | https://api.local/app | https://api.yourdomain.com/app |
| Панель Strapi CMS | http://<VM_IP>:1337/admin | https://admin.local/admin | https://admin.yourdomain.com/admin |
| Аналитика Umami | http://<VM_IP>:3005 | https://analytics.local | https://analytics.yourdomain.com |
| Мониторинг OpenObserve | http://<VM_IP>:5080 | https://monitor.local | https://monitor.yourdomain.com |
| Поисковый движок (Meilisearch) | 127.0.0.1:7700 | https://search.local | https://search.yourdomain.com |
Назначение каждого публичного URL в .env:
STOREFRONT_PUBLIC_URL: Витрина Next.js (порт 8000 внутри Docker или публичный домен).MEDUSA_BACKEND_PUBLIC_URL: API Medusa и Панель администратора (/app).STRAPI_PUBLIC_URL: Strapi CMS (/admin); ссылки предпросмотра используют STOREFRONT_PUBLIC_URL.MEILISEARCH_PUBLIC_URL: Публичный URL для мгновенного клиентского поиска (Профиль A:http://127.0.0.1:7700, Профиль B:https://search.local, Профиль C:https://search.yourdomain.com).MINIO_PUBLIC_URL: Публичный префикс для медиафайлов (Профиль A: http://IP:9001/mystore, Профиль B/C: https://api.*/minio/mystore).STOREFRONT_URL: Только для внутренней сети Docker (http://storefront:8000), используется для ревалидации кэша Medusa -> Storefront.
ОБЯЗАТЕЛЬНО настроить до запуска Фазы 1:
• Секретные ключи (openssl rand -hex 32): POSTGRES_PASSWORD, MEILI_MASTER_KEY, все ключи STRAPI_*, MEDUSA_JWT_SECRET, MEDUSA_COOKIE_SECRET, REVALIDATE_SECRET, UMAMI_APP_SECRET.
• Учетные записи администраторов: MEDUSA_ADMIN_EMAIL, MEDUSA_ADMIN_PASSWORD, MINIO_ROOT_USER, MINIO_ROOT_PASSWORD, UMAMI_USERNAME, UMAMI_PASSWORD.
• Публичные URL: Выберите Профиль A, B или C, как описано выше.
Оставить пустыми до выполнения соответствующей фазы:
• Фаза 4: STRAPI_API_TOKEN_FOR_MEDUSA, STRAPI_API_TOKEN_FOR_FRONT
• Фаза 6: MEDUSA_PUBLISHABLE_KEY
• Фаза 7: MEILI_SEARCH_KEY
• Фаза 8: UMAMI_WEBSITE_ID
Правило панели Medusa: Всегда сохраняйте MEDUSA_NODE_ENV=production в Docker. Никогда не указывайте development: панель скомпилирована под продакшен, а режим dev приводит к белому экрану.
5. Автодеплой через GitHub Actions CI/CD
Проект включает готовые пайплайны для автоматической сборки Docker-контейнеров и доставки на сервер при каждом git push:
- Добавьте IP сервера и приватный SSH-ключ в Repository Secrets на GitHub.
- Каждый коммит в ветку main запускает сборку оптимизированных контейнеров Next.js и Medusa.
- На сервер отправляется сигнал для бесшовного обновления контейнеров без простоя (Zero-Downtime).
- 4. (Приватный репозиторий) Создайте GitHub Personal Access Token (Classic) с правами
repo,workflowиread:packages, затем выполните вход в GitHub Container Registry на вашем VPS:
echo "<YOUR_PAT>" | docker login ghcr.io -u <YOUR_GITHUB_USERNAME> --password-stdinПроцесс Развертывания в 10 Фаз (Phases 1-10)
| Фаза | Запускаемые Сервисы | Профиль A | Профиль B / C (Локальная сеть и Продакшен) |
|---|---|---|---|
| Фаза 1: | Базы данных и инфраструктура (Postgres, Redis, MinIO, Meilisearch) | ✅ | ✅ |
| Фаза 2: | Обратный прокси Caddy и автоматический SSL (hosts в Профиле B) | ⏭ Пропустить (Не требуется в Профиле A) | ✅ Сразу после Фазы 1, до запуска Strapi |
| Фаза 3: | Движок Strapi CMS (Загрузка образа из GHCR) | ✅ | ✅ |
| Фаза 4: | API-токены Strapi -> сохранить в .env | ✅ | ✅ |
| Фаза 5: | Коммерческое ядро Medusa 2.0 (Загрузка образа из GHCR) | ✅ | ✅ |
| Фаза 6: | Публичный ключ Medusa -> сохранить в .env | ✅ | ✅ |
| Фаза 7: | Ключ поиска Meilisearch -> сохранить в .env | ✅ | ✅ |
| Фаза 8: | Аналитика Umami (До запуска витрины) | Необязательно | ✅ |
| Фаза 9: | Фронтенд Next.js (Сборка и развертывание с GitHub Actions) | ✅ | ✅ |
| Фаза 10: | Стек наблюдаемости и логов (OpenObserve, Vector, cAdvisor) | Необязательно | Рекомендуется |
Фаза 1: Запуск Баз Данных (PostgreSQL & Redis)
Запуск PostgreSQL с изолированными схемами под Medusa, Strapi и Umami, а также Redis для сессий и кэша.
docker compose up -d postgres redis meilisearch minio minio-setupДождитесь перехода всех сервисов в статус healthy: docker compose ps
Фаза 2: Шлюз Caddy и Автоматические Сертификаты SSL
Запуск обратного прокси Caddy для автоматического получения и продления SSL-сертификатов Let's Encrypt.
docker compose up -d caddydocker compose logs -f caddyНастройка файла hosts в Windows для Профиля B:
Откройте C:\Windows\System32\drivers\etc\hosts от имени Администратора и добавьте строку:192.168.1.103 store.local api.local admin.local analytics.local monitor.local
(Замените 192.168.1.103 на IP вашей виртуальной машины. Не добавляйте Meilisearch — он должен оставаться строго внутренним).
Фаза 3: Запуск Strapi CMS v5
Скачивание образа Strapi CMS, подключение к базе данных и ожидание готовности порта 1337.
docker compose pull strapidocker compose up -d strapidocker compose logs -f strapiДождитесь, пока сервер начнет слушать порт 1337 (1–3 минуты при первом запуске). Откройте панель Strapi (Профиль B: https://admin.local/admin, Профиль A: http://<VM_IP>:1337/admin) и зарегистрируйте учетную запись администратора.
Фаза 4: Извлечение Токенов Strapi и Запись в .env
Автоматическая генерация сервисного токена для доступа фронтенда Next.js к блокам Strapi.
- Скрипт strapi-token-init.js извлекает административный токен.
- Переменная STRAPI_API_TOKEN сохраняется в файл .env.
- 3. Для витрины (
STRAPI_API_TOKEN_FOR_FRONT): Выберите токенRead-Only, нажмите Regenerate и скопируйте полученное значение в переменнуюSTRAPI_API_TOKEN_FOR_FRONTв файле.env.
Фаза 5: Запуск Движка MedusaJS v2
Запуск контейнера Medusa, применение миграций базы данных и создание учетной записи супер-администратора.
docker compose pull medusadocker compose up -d medusadocker compose logs -f medusaАвтоматические шаги при первом запуске: Миграции БД через db:migrate (2–5 минут) -> создание суперпользователя -> готовность API на порту 9000. Откройте Medusa Admin по адресу https://api.local/app (Профиль B) или http://<VM_IP>:9000/app (Профиль A) и войдите с помощью MEDUSA_ADMIN_EMAIL и MEDUSA_ADMIN_PASSWORD.
Фаза 6: Каналы Продаж и Публичные Ключи Medusa
Генерация ключа Publishable Key для взаимодействия витрины с корзиной и каталогом товаров.
- Создание и авторизация администратора.
- Ключ привязывается к переменной NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY.
- 3. ОЧЕНЬ ВАЖНО: Откройте созданный ключ > вкладка Sales Channels > привяжите к Default Sales Channel. Без этого шага товары не будут отображаться на витрине.
Фаза 7: Развертывание Поискового Движка Meilisearch
Запуск контейнера Meilisearch для мгновенного поиска товаров с автодополнением и опечаткоустойчивостью.
curl -H "Authorization: Bearer <MEILI_MASTER_KEY>" http://127.0.0.1:7700/keysСкопируйте Default Search API Key и вставьте в переменную MEILI_SEARCH_KEY в файле .env (интерактивный скрипт извлекает его автоматически).
Фаза 8: Запуск Аналитики Umami
Запуск независимой аналитической платформы Umami без использования cookies и генерация ID веб-сайта.
docker compose up -d umamiОткройте панель Umami (Профиль B: https://analytics.local, Профиль A: http://<VM_IP>:3005). Войдите (admin / umami), перейдите в Settings > Websites > Add website и скопируйте сгенерированный Website ID в переменную UMAMI_WEBSITE_ID в .env.
Фаза 9: Запуск Витрины Next.js 16
Сборка фронтенда, подключение к готовым сервисам и открытие доступа к главной странице магазина.
1. Переменные Сборки и API-Ключи:
Пути к Medusa и Strapi передаются в контейнер на этапе сборки.
1. STOREFRONT_BUILD_ARGS (Переменные сборки)
Содержит переменные сборки Next.js. Скопируйте шаблон выше и подставьте ключи, сгенерированные на предыдущих фазах.
MEDUSA_BACKEND_URL=http://medusa:9000NEXT_PUBLIC_MEDUSA_BACKEND_URL=https://api.yourdomain.comNEXT_PUBLIC_STRAPI_URL=https://admin.yourdomain.comNEXT_PUBLIC_BASE_URL=https://store.yourdomain.comNEXT_PUBLIC_MEILISEARCH_HOST=https://search.yourdomain.comNEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY=pk_...NEXT_PUBLIC_MEILISEARCH_SEARCH_KEY=...NEXT_PUBLIC_UMAMI_WEBSITE_ID=...NEXT_PUBLIC_DEFAULT_REGION=USDEFAULT_LOCALE=en-USNEXT_PUBLIC_MEILISEARCH_INDEX_NAME=productsNEXT_PUBLIC_ENABLE_IRAN_FEATURES=false2. REGISTRY_URL
URL реестра компонентов. Значение по умолчанию — публичный реестр Loomix Blocks:https://raw.githubusercontent.com/landa33/loom-blocks-registry/main/src/modules
3. GITHUB_PAT (Опционально)
GitHub Personal Access Token (Classic). Требуются разрешения repo, workflow и read:packages. Используется для загрузки образов GHCR, запуска CI/CD и доступа к приватным реестрам.
4. DEPLOY_PATH
Абсолютный путь к директории проекта на вашем Linux VPS (напр., /root/loomix-commerce). Необходим для того, чтобы Self-Hosted Runner мог найти проект Docker Compose.
2. Ультралегкая Standalone-Сборка:
Режим Standalone в Next.js снижает размер итогового Docker-образа до менее чем 150 МБ.
3. Проверка Сети и Доступности:
Проверка порта 8000 и подключение к внутренней сети прокси Caddy.
4. Запуск Витрины в Продакшене:
docker compose pull storefrontdocker compose up -d storefrontФаза 10: Мониторинг и Логирование (OpenObserve & Vector)
Запуск Vector и OpenObserve для мониторинга системных метрик, памяти, нагрузки на CPU и сбора логов.
docker compose up -d openobserve vector cadvisor docker-stats-exporterЦентральная панель управления OpenObserve:
Откройте https://monitor.yourdomain.com (Профиль C), https://monitor.local (Профиль B) или http://<VM_IP>:5080 (Профиль A). Войдите с root-учетными данными OpenObserve.
Потоки телеметрии и собираемые журналы:
docker_logs: Единый журнал всех контейнеров и мгновенный поиск ошибок по микросервисам.
caddy_access: Входящий веб-трафик HTTP, IP-адреса клиентов, HTTP-коды статусов (2xx/4xx/5xx) и пути запросов, отправляемые напрямую из JSON-логов Caddy через Vector.
docker_stats: Потребление оперативной памяти в реальном времени, нагрузка на CPU % и сетевой ввод/вывод по каждому контейнеру через cAdvisor.
host_metrics: Общая загрузка процессора, использование оперативной памяти и статистика дискового ввода-вывода хост-сервера.
Мгновенные оповещения в Telegram:
В панели OpenObserve перейдите в Reliability > Destinations для подключения вебхука вашего Telegram-бота (https://api.telegram.org/bot<TOKEN>/sendMessage), затем создайте правила оповещений в Reliability > Alerts для уведомлений в реальном времени при ошибках 500.
6. Первичная Синхронизация Данных между Medusa и Strapi
Автоматическая процедура, которая считывает товары из Medusa и создает соответствующие блоки в Strapi.
Запуск Первой Синхронизации:
Выполните команду внутри контейнера Strapi для генерации структуры главной страницы:
2. Синхронизация модульных блоков Loomix (sync-loom-component.js)
В панели Strapi в разделе Storefront Management нажатие + Add to Storefront (Queue) или Remove Style (Queue) помещает изменения в очередь в sync-history.json. При нажатии Update Storefront пресеты синхронизируются и запускается процесс сборки и развертывания в GitHub Actions.
Переменные окружения для синхронизации в продакшене:
Задайте эти переменные в website-admin/.env и в корневом файле .env сервера. Убедитесь, что токен имеет разрешения 'repo' и 'workflow':
GITHUB_DEPLOY_TOKEN=ghp_your_personal_access_token # Requires 'repo' and 'workflow' scopesGITHUB_DEPLOY_REPO=your_username/your_repo_name7. Переключение между Профилями Развертывания
Инструкция по миграции с Профиля A на Профиль B или изменению доменных имен:
| Тип Изменения | Перезапускаемые Сервисы |
|---|---|
| Публичные URL в .env | Strapi, Medusa, Storefront (сначала запустите экшен в GitHub Actions, затем скачайте образ) |
| Настройка MEDUSA_ALLOW_HTTP_COOKIES | Только контейнер Medusa |
| Добавление Caddy (Переход от Профиля A к B) | Запуск Caddy (docker compose up -d caddy); загрузка новых образов |
| Файл hosts (Профиль B) | На сервере перезапуск не требуется; отредактируйте файл hosts в Windows на вашей рабочей машине |
# 1. Edit .env — switch to Profile B URLs, set MEDUSA_ALLOW_HTTP_COOKIES=falsenano .env # 2. Add hosts entry on Windows # 3. Start Caddydocker compose up -d caddy # 4. Pull new images:docker compose pull strapi medusa && docker compose up -d strapi medusa8. Обновление Сервисов до Последних Версий
Запустите скрипт server-update.sh для загрузки свежих релизов без риска потери данных в БД.
9. Полезные Команды Администрирования и Обслуживания
Команды Docker для просмотра логов, перезапуска сервисов и резервного копирования:
./setup.sh # On Linux / macOS.\setup.bat # On Windows10. Внутренняя Сеть и Карта Портов
Внутренняя Сеть Контейнеров (Internal Bridge Network):
- Витрина (Storefront): :8000
- Medusa API + Панель управления: :9000
- Strapi CMS: :1337
- Meilisearch: :7700
- Консоль MinIO: :9001
- Аналитика Umami: :3005
- Мониторинг OpenObserve: :5080
Доменные Имена, Обрабатываемые Caddy:
- https://store.local -> storefront:8000
- https://api.local -> medusa:9000
- https://admin.local -> strapi:1337
- https://analytics.local -> umami:3000
- https://monitor.local -> openobserve:5080
- https://api.local/minio/ -> minio:9000
Изолированная Сеть loomix-network:
Контейнеры связываются между собой внутри сети по стандартным именам сервисов (напр., http://storefront:8000, http://medusa:9000, http://meilisearch:7700). Сервис Meilisearch является строго внутренним и никогда не должен публиковаться во внешнюю сеть.
Сводка Основных Команд Управления
docker compose psdocker compose logs -f medusadocker compose logs -f strapidocker compose logs -f storefrontdocker compose logs -f openobservedocker builder prune -fdocker system prune -fdocker compose downdocker compose up -d