Table of Contents

Разворачивание Корпоративного Сервера или Публикатора без Kubernetes (docker-compose) - FerretDB

Продукты: МоиОтчеты Корпоративный Сервер, МоиОтчеты Публикатор

Общее описание

Данная инструкция представляет собой пример развёртывания сервера отчётов (Корпоративный Сервер / Публикатор) с использованием FerretDB в качестве базы данных и RabbitMQ в качестве брокера сообщений. FerretDB обеспечивает совместимость с протоколом MongoDB, при этом используя PostgreSQL в качестве хранилища.

Все конфигурационные файлы в данном каталоге являются примерами и предназначены для локального тестирования и ознакомления. Для рабочего контура необходимо адаптировать настройки под ваше окружение.

Важная информация о поддержке

Компания «Быстрые отчеты» оказывает поддержку только на продукты МоиОтчеты (Корпоративный Сервер, Публикатор).

Мы не несём ответственности за работу, настройку и поддержку следующих компонентов:

  • FerretDB (PostgreSQL, база данных)
  • RabbitMQ (брокер сообщений)
  • PostgreSQL (внутренняя СУБД FerretDB)
  • Любые другие сторонние сервисы и контейнеры, представленные в данном примере

Если у вас возникнут проблемы с базой данных или сторонними сервисами, обратитесь к их документации или соответствующим сообществам.

Предварительные требования

Перед началом установки убедитесь, что на вашей системе установлены:

  1. Docker (версия 20.10+ рекомендуется) - инструкция по установке

  2. Docker Compose (плагин для Docker, версия v2+) - обычно входит в Docker Desktop. Проверить можно командой:

    docker compose version
    
  3. Достаточное количество оперативной памяти (рекомендуется не менее 4 ГБ свободной RAM для всех контейнеров).

  4. Порт 8080 (веб-интерфейс) должен быть свободен на хост-машине.

Содержимое каталога

Файл Назначение
docker-compose.yml Описание всех сервисов (контейнеров), их связей и настроек
.env Переменные окружения - имя и версия docker-образов продукта
appsettings.Production.json Конфигурация приложения: подключение к БД, брокеру, внутренние ключи безопасности, адреса сервисов

Переменные окружения (.env)

Файл .env определяет параметры, которые подставляются в docker-compose.yml через синтаксис ${ПЕРЕМЕННАЯ}.

FRC_SOURCE=xn--80akiaokt3b4b.xn--90aia9aifhdb2cxbdg.xn--p1ai/repository/docker-registry/moiotchety-corporate-server
FRC_VERSION=2026.2.13

Пояснения:

  • FRC_SOURCE - адрес docker-регистри (registry), откуда будут скачиваться docker-образы продукта МоиОтчеты.
  • FRC_VERSION - версия продукта. Убедитесь, что указанная версия существует в реестре и у вас есть доступ к ней.

Важно: Не изменяйте FRC_SOURCE, если вы не уверены в корректности адреса реестра. Убедитесь, что ваш docker-демон имеет доступ к этому реестру.

Конфигурация приложения (appsettings.Production.json)

Этот файл содержит основные настройки приложения. Рассмотрим ключевые секции:

{
  "Auth": {
    "UseOpenId": false,
    "UseLocal": true
  },
  "MainConfig": {
    "InternalHeaders": {
      "S56nHMSzjQzXYx5KJJsU3cjU": "000000000000000000000001",
      "x2aHtuSsxFeYqE8xPTaxAnbH": "000000000000000000000002",
      "QNpq2nyzvDNSCBLtVhMJ9e8m": "000000000000000000000003",
      "9MXgeFwLNjeUrJvw7N2aQv9F": "000000000000000000000004",
      "227881200f7cd43f238b327d": "000000000000000000000005"
    },
    "Frontend": {
      "Mixins": {
        "Head": "",
        "Body": ""
      },
      "InvariantLocale": ""
    },
    "License": "",
    "Server": {
      "Title": "МоиОтчеты Сервисные решения",
      "CorporateServerMode": true
    },
    "Rabbit": {
      "Host": "rabbitmq",
      "Port": 5672,
      "UserName": "fastreports",
      "Password": "Qwerty!23456"
    },
    "Database": {
      "ConnectionString": "mongodb://fastreport:Qwerty!23456@ferret:27017/ReportStore?maxPoolSize=100&waitQueueMultiple=100",
      "DatabaseName": "ReportStore"
    }
  },
  "Gateway": {
    "BackendUrl": "http://fr-backend:80",
    "InternalKey": "QNpq2nyzvDNSCBLtVhMJ9e8m",
    "SignInPagePath": "/account/signin?r={0}",
    "MaxConcurrentRequests": 200,
    "RequestQueueLimit": 5000
  },
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug"
    }
  },
  "Services": {
    "Items": {
      "OnlineDesigner": {
        "Type": "Static",
        "Urls": [
          "http://fr-onlinedesigner:80"
        ]
      },
      "Backend": {
        "Type": "Static",
        "Urls": [
          "http://fr-backend:80"
        ]
      },
      "FrontendApp": {
        "Type": "Static",
        "Urls": [
          "http://fr-app:80"
        ]
      },
      "Fonts": {
        "Type": "Static",
        "Urls": [
          "http://fr-fonts:80"
        ]
      },
      "StaticPreviewApp": {
        "Type": "Static",
        "Urls": [
          "http://fr-staticpreview:80"
        ]
      },
      "AdminApp": {
        "Type": "Static",
        "Urls": [
          "http://fr-admin:80"
        ]
      }
    }
  },
  "Designer": {
    "BackendUrl": "http://fr-backend:80",
    "InternalKey": "x2aHtuSsxFeYqE8xPTaxAnbH"
  },
  "WorkerCore": {
    "BackendUrl": "http://fr-backend:80",
    "InternalKey": "S56nHMSzjQzXYx5KJJsU3cjU"
  },
  "Scheduler": {
    "BackendUrl": "http://fr-backend:80",
    "InternalKey": "9MXgeFwLNjeUrJvw7N2aQv9F"
  },
  "Fonts": {
    "BackendUrl": "http://fr-backend:80",
    "InternalKey": "227881200f7cd43f238b327d"
  }
}

Аутентификация

  • UseLocal: true - используется встроенная локальная авторизация (логин/пароль).
  • UseOpenId: false - внешний OpenID Connect-провайдер не используется. Для рабочего контура рекомендуется настроить OIDC.

Внутренние заголовки безопасности (InternalHeaders)

"InternalHeaders": {
  "S56nHMSzjQzXYx5KJJsU3cjU": "000000000000000000000001",
  "x2aHtuSsxFeYqE8xPTaxAnbH": "000000000000000000000002",
  "QNpq2nyzvDNSCBLtVhMJ9e8m": "000000000000000000000003",
  "9MXgeFwLNjeUrJvw7N2aQv9F": "000000000000000000000004",
  "227881200f7cd43f238b327d": "000000000000000000000005"
}

Каждая пара ключ:значение - это уникальный идентификатор и секрет для внутренней коммуникации между сервисами продукта.

Предупреждение безопасности:

  • Эти ключи должны быть уникальными и не должны совпадать с какими-либо другими секретами в системе.
  • Они используются для авторизации внутренних запросов между микросервисами (Gateway, Backend, Designer, WorkerCore, Scheduler, Fonts).
  • Никогда не публикуйте эти ключи в открытом доступе.
  • Для рабочего контура обязательно замените примерные значения на ваши собственные случайные строки.

Подключение к RabbitMQ (брокер сообщений)

"Rabbit": {
  "Host": "rabbitmq",
  "Port": 5672,
  "UserName": "fastreports",
  "Password": "Qwerty!23456",
  ...
}
  • Host - имя сервиса RabbitMQ из docker-compose.yml (в данном примере - rabbitmq).
  • Port - порт AMQP (по умолчанию 5672).
  • UserName / Password - учётные данные для подключения к RabbitMQ.

Предупреждение безопасности: Пароль Qwerty!23456 и логин fastreports указаны только для примера. В рабочем контуре необходимо использовать надёжные, случайно сгенерированные учётные данные. Не используйте этот пароль в реальных развертываниях.

Подключение к базе данных (FerretDB)

"Database": {
  "ConnectionString": "mongodb://fastreport:Qwerty!23456@ferret:27017/ReportStore&maxPoolSize=100&waitQueueMultiple=100",
  "DatabaseName": "ReportStore"
}
  • ConnectionString указывает на сервис ferret (FerretDB), который эмулирует MongoDB-совместимый интерфейс поверх PostgreSQL.
  • fastreport:Qwerty!23456 - логин и пароль для подключения к базе данных.
  • ReportStore - имя базы данных.

Предупреждение безопасности: Пароль базы данных Qwerty!23456 указан только для примера. Для рабочего контура обязательно замените его на надёжный пароль. Убедитесь, что пароли в appsettings.Production.json, docker-compose.yml и в настройках PostgreSQL/FerretDB совпадают.

Gateway, Designer, WorkerCore, Scheduler, Fonts

Каждый из этих сервисов содержит поле InternalKey, которое должно совпадать с соответствующим ключом из секции InternalHeaders. Это обеспечивает безопасную внутреннюю коммуникацию.

Файл docker-compose.yml

services:
  postgres:
    image: ghcr.io/ferretdb/postgres-documentdb:17-0.107.0-ferretdb-2.7.0
    restart: always
    environment:
      - POSTGRES_USER=fastreport
      - POSTGRES_PASSWORD=Qwerty!23456
      - POSTGRES_DB=postgres
    volumes:
      - ./postgres:/var/lib/postgresql/data
    networks: 
      - fr-cs
  ferret:
    image: ghcr.io/ferretdb/ferretdb:2.7.0
    restart: always
    environment:
      - FERRETDB_AUTH=true
      - FERRETDB_SETUP_DATABASE=ReportStore
      - FERRETDB_POSTGRESQL_URL=postgres://fastreport:Qwerty!23456@postgres:5432/postgres
    networks: 
      - fr-cs
  rabbitmq:
    image: bitnamilegacy/rabbitmq:3.9.27-debian-11-r9
    volumes:
      - ./rabbitmq:/bitnami
    restart: always
    networks: 
      - fr-cs
    environment:
      - RABBITMQ_USERNAME=fastreports
      - RABBITMQ_PASSWORD=Qwerty!23456
  fr-backend:
    image: ${FRC_SOURCE}-backend:debian-${FRC_VERSION}
    restart: always
    volumes:
      - ./appsettings.Production.json:/app/appsettings.Production.json:ro
    networks: 
      - fr-cs
  fr-gateway:
    image: ${FRC_SOURCE}-gateway:debian-${FRC_VERSION}
    ports:
      - 8080:80
    restart: always
    volumes:
      - ./appsettings.Production.json:/app/appsettings.Production.json:ro
    networks: 
      - fr-cs
  fr-fonts:
    image: ${FRC_SOURCE}-fonts:debian-${FRC_VERSION}
    restart: always
    volumes:
      - ./appsettings.Production.json:/app/appsettings.Production.json:ro
    networks: 
      - fr-cs
  fr-app:
    image: ${FRC_SOURCE}-app:debian-${FRC_VERSION}
    restart: always
    volumes:
      - ./appsettings.Production.json:/app/appsettings.Production.json:ro
    networks: 
      - fr-cs
  fr-staticpreview:
    image: ${FRC_SOURCE}-static-preview:debian-${FRC_VERSION}
    restart: always
    volumes:
      - ./appsettings.Production.json:/app/appsettings.Production.json:ro
    networks: 
      - fr-cs
  fr-onlinedesigner:
    image: ${FRC_SOURCE}-designer:debian-${FRC_VERSION}
    restart: always
    volumes:
      - ./appsettings.Production.json:/app/appsettings.Production.json:ro
    networks: 
      - fr-cs
  fr-admin:
    image: ${FRC_SOURCE}-admin:debian-${FRC_VERSION}
    restart: always
    volumes:
      - ./appsettings.Production.json:/app/appsettings.Production.json:ro
    networks: 
      - fr-cs
  fr-workercore:
    image: ${FRC_SOURCE}-workercore:debian-${FRC_VERSION}
    restart: always
    volumes:
      - ./appsettings.Production.json:/app/appsettings.Production.json:ro
    networks: 
      - fr-cs
    deploy:
      mode: replicated
      replicas: 1
      endpoint_mode: vip
  fr-scheduler:
    image: ${FRC_SOURCE}-scheduler:debian-${FRC_VERSION}
    restart: always
    volumes:
      - ./appsettings.Production.json:/app/appsettings.Production.json:ro
    networks: 
      - fr-cs
networks: 
  fr-cs:
    driver: bridge

Файл docker-compose.yml описывает все контейнеры, которые будут запущены.

Примечание: Все сервисы продукта (fr-*) используют один и тот же конфигурационный файл appsettings.Production.json, который монтируется в контейнер как read-only том (:ro). Благодаря этому при обновлении образов конфигурация сохраняется.

Предупреждение безопасности:

  • Образы контейнеров (image) берутся из переменных .env. Убедитесь, что вы доверяете источнику образов.
  • Установленные в примере пароли (Qwerty!23456) используются только для тестирования. Замените их перед использованием в рабочем контуре.

Установка и запуск

Шаг 1. Создайте файлы конфигурации

В данном каталоге должны находятся файлы:

  • .env
  • appsettings.Production.json
  • docker-compose.yml

Отредактируйте файлы, заменив пароли на свои.

Шаг 2. Запустите контейнеры

docker compose up -d

Данная команда создаст и запустит все контейнеры в фоновом режиме (-d).

Шаг 3. Проверьте, что все контейнеры запущены

docker compose ps

Убедитесь, что все контейнеры имеют статус running. Первый запуск может занять несколько минут - Docker будет скачивать образы из реестра. А так же будут применены миграции. Отслеживайте логи что миграции применились у сервиса backend.

Шаг 4. Откройте веб-интерфейс

Перейдите в браузере по адресу:

http://localhost:8080

Шаг 5. Войдите в систему

Используйте учётные данные по умолчанию (только для тестирования!):

  • Логин: admin@example.com
  • Пароль: admin

Шаг 6. Панель администрирования

Для доступа к панели администрирования перейдите по ссылке:

http://localhost:8080/admin

Остановка сервера

Для остановки и удаления всех контейнеров выполните:

docker compose down

Для остановки с сохранением данных (томов) просто выполните docker compose stop.

Полное удаление данных (включая базу)

Предупреждение: Следующая команда удалит все данные из PostgreSQL, FerretDB, RabbitMQ и загруженные отчёты. Используйте только если хотите начать с чистого состояния.

docker compose down -v

Полезные команды

Команда Описание
docker compose logs -f Просмотр логов всех сервисов в реальном времени
docker compose logs fr-backend Лог только сервиса fr-backend
docker compose restart Перезапуск всех сервисов
docker compose ps Статус всех контейнеров
docker compose stop Остановка контейнеров без удаления

Устранение неполадок

  • Контейнер не запускается - проверьте логи: docker compose logs <имя_сервиса>. Убедитесь, что образ доступен в реестре и параметры .env корректны.
  • Не удаётся подключиться к веб-интерфейсу - убедитесь, что порт 8080 не занят другим приложением. Проверьте: docker compose ps. Проверьте что применены все миграции через логи сервиса backend.
  • Ошибки подключения к базе данных - убедитесь, что PostgreSQL и FerretDB полностью инициализировались перед запуском сервисов продукта. Подождите 1–2 минуты после запуска.
  • Ошибки подключения к RabbitMQ - проверьте, что учётные данные в appsettings.Production.json совпадают с настройками контейнера RabbitMQ в docker-compose.yml.