MAATRIX / Блог / Stirling PDF на сервере: частые ошибки и решения

Stirling PDF на сервере: частые ошибки и решения

MAATRIX

Stirling PDF — швейцарский нож для работы с PDF: слияние, разбивка, водяные знаки, OCR, конвертация в Word и обратно — всё это можно поднять одним контейнером на своём сервере вместо десятка онлайн-сервисов с чужими лимитами и чужим доступом к вашим документам. Но именно из-за широты возможностей у него больше точек отказа, чем у обычного статического сайта: часть функций требует Tesseract, часть — LibreOffice, а часть упирается в настройки реверс-прокси и памяти сервера. Разберём самые частые проблемы по схеме «симптом — причина — решение».

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Какой образ ставить и почему это первая причина проблем

Прежде чем разбирать конкретные ошибки, важно понять один момент: Stirling PDF распространяется несколькими вариантами Docker-образа, и добрая половина «странных» ошибок объясняется тем, что выбран не тот вариант. Официальный образ — stirlingtools/stirling-pdf, но у него исторически существуют облегчённые сборки без OCR и без LibreOffice, рассчитанные на минимальный размер и память, и полная сборка со всем инструментарием на борту. Названия тегов между релизами менялись (в разных версиях встречались варианты вроде latest, latest-ultra-lite, latest-fat), поэтому точный список актуальных тегов и что каждый из них включает всегда стоит сверять в официальном README проекта на GitHub перед разворачиванием — не полагайтесь на старую статью или чужой docker-compose годичной давности.

Минимальный рабочий вариант выглядит так:

services:
  stirling-pdf:
    image: stirlingtools/stirling-pdf:latest
    container_name: stirling-pdf
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - ./stirling/trainingData:/usr/share/tessdata
      - ./stirling/customFiles:/customFiles
      - ./stirling/logs:/logs
      - ./stirling/configs:/configs
    environment:
      - DOCKER_ENABLE_SECURITY=false
      - LANGS=en_US
    deploy:
      resources:
        limits:
          memory: 2g

Если сервер только разворачивается с нуля, порядок такой: сначала поднимаете Docker и Docker Compose, затем сеть и домен, и уже потом контейнер приложения — этот путь подробно описан в статье про установку Docker с нуля. Дальше — по конкретным ошибкам.

OCR не находит язык или не запускается вообще

Симптом: кнопка распознавания текста либо выдаёт ошибку про отсутствующий языковой пакет, либо просто ничего не делает с отсканированным PDF. Первая причина — вы используете облегчённый образ, в котором Tesseract не установлен в принципе: в таком случае OCR не заработает никаким конфигом, нужен образ с полным набором инструментов.

Вторая причина, даже на полном образе, — не хватает данных нужного языка. Русский язык не входит в набор по умолчанию почти нигде, его нужно указать явно:

environment:
  - LANGS=eng,rus

После смены переменной пересоздайте контейнер (простого restart может быть недостаточно, если образ докачивает языковые данные при старте):

docker compose up -d --force-recreate stirling-pdf

Проверить, что языковые файлы реально появились внутри контейнера, можно так:

docker exec stirling-pdf ls /usr/share/tessdata

Если файла rus.traineddata там нет, а сеть контейнера ограничена (например, isolated network без выхода наружу), контейнер не смог скачать пакет при первом старте — временно дайте ему доступ в интернет или положите файл языка в volume /usr/share/tessdata вручную, скачав его заранее на хосте.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

PDF в DOCX или XLSX не конвертируется

Симптом: простые операции (слияние, поворот, сжатие) работают, а любая конвертация в офисные форматы и обратно падает с ошибкой или зависает. Конвертация PDF↔Office в Stirling PDF выполняется через LibreOffice, который запускается внутри того же контейнера, — и в облегчённых образах его тоже может не быть.

Проверить, установлен ли LibreOffice в контейнере, можно напрямую:

docker exec stirling-pdf which soffice

Пустой ответ означает, что бинарника нет и конвертация в Word/Excel/PowerPoint технически недоступна на этом образе — нужен вариант с полным набором инструментов (в терминологии проекта это обычно «полный» / «fat»-образ, но, как и с OCR, точное имя тега смотрите в актуальной документации на момент установки). Если soffice на месте, а конвертация всё равно падает — часто дело в нехватке памяти: LibreOffice сам по себе прожорлив, и на конвертации многостраничных документов процесс может быть убит OOM-киллером ещё до вывода внятной ошибки в интерфейсе. Смотрите логи контейнера сразу после неудачной попытки:

docker logs --tail 100 stirling-pdf

Строка вида Killed или резкий обрыв процесса в логе — верный признак нехватки памяти, а не проблемы с самим форматом файла.

Контейнер падает или зависает на больших файлах

Java-процесс Stirling PDF и вызываемый им LibreOffice вместе способны съедать заметно больше памяти, чем кажется по размеру исходного PDF — особенно на файлах с большим числом страниц или высоким разрешением сканов при OCR. На серверах с 1–2 ГБ RAM это частая причина, по которой обработка «просто зависает» без явной ошибки в браузере.

Первым делом проверьте, не сработал ли OOM-killer на уровне хоста:

dmesg | grep -i "out of memory"

Если да — контейнер убивает ядро, а не сам Stirling PDF. Быстрое решение — не задавать контейнеру жёсткий лимит памяти меньше 2 ГБ и подстраховаться swap-файлом, чтобы кратковременные пики не валили процесс:

fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

Подробно про то, какой размер swap разумен для конкретного объёма RAM и когда он вообще нужен, разобрано в статье про правильный размер swap для VPS. Учтите: swap спасает от падения, но не от медленной обработки — если сервер регулярно упирается в память на конвертации и OCR, честнее увеличить объём RAM, чем бесконечно наращивать своп.

Загрузка большого файла обрывается через nginx (413 или разрыв соединения)

Симптом: маленькие PDF грузятся и обрабатываются нормально, а файл на 20–50 МБ обрывается на загрузке с ошибкой 413 Request Entity Too Large или просто зависает без ответа сервера. Причина почти всегда в реверс-прокси перед контейнером, а не в самом Stirling PDF: nginx по умолчанию ограничивает размер тела запроса в 1 МБ.

Увеличьте лимит в конфиге сайта или в http-блоке:

client_max_body_size 200M;

Не забудьте перезагрузить конфиг после правки:

nginx -t && systemctl reload nginx

Если файл всё равно не проходит — вторая типовая причина в том же семействе — таймауты на чтение тела запроса при медленной загрузке с клиента. Подробный разбор именно этой связки собран в статье nginx как реверс-прокси на сервере: частые ошибки и решения — там же логика для тех, кто ставит Stirling PDF за Traefik, а не за nginx: если выбираете между ними с нуля, сравнение подходов есть в статье про Traefik как реверс-прокси для Docker.

Долгая OCR-задача обрывается таймаутом 504

Отдельная и очень частая жалоба: небольшие операции работают мгновенно, а распознавание текста на объёмном скан-документе через минуту-другую обрывается ошибкой 504 Gateway Timeout прямо в браузере — хотя сам Stirling PDF, если зайти напрямую по IP и порту 8080 в обход прокси, эту же задачу спокойно доводит до конца. Значит, дело не в приложении, а в том, что реверс-прокси разрывает соединение раньше, чем контейнер успевает ответить: у nginx таймаут ожидания ответа от бэкенда по умолчанию всего 60 секунд.

Увеличьте его для локации, за которой стоит Stirling PDF:

location / {
    proxy_pass http://127.0.0.1:8080;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;
}

300 секунд — разумный запас для OCR многостраничных документов, но если у вас регулярно обрабатываются очень объёмные сканы, ориентируйтесь по факту: засеките, сколько реально занимает обработка типового файла в вашем окружении (это будет зависеть от числа страниц, качества скана и ресурсов сервера), и закладывайте таймаут с запасом в полтора-два раза. Общая механика этой ошибки и то, почему она чаще всего живёт именно в конфиге прокси, а не в приложении, разобрана в статье про 504 Gateway Timeout в nginx.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Почему у меня вообще нет вкладки OCR или конвертации в Word в интерфейсе?

Скорее всего вы используете облегчённый вариант Docker-образа без Tesseract и LibreOffice — переключитесь на полный образ, сверив точное имя тега в актуальном README проекта.

Стоит ли включать встроенную авторизацию (DOCKER_ENABLE_SECURITY), если сервис доступен только вам?

Если инстанс смотрит наружу без ограничения по IP или VPN, включайте — иначе любой, кто найдёт адрес, получит доступ к загрузке и обработке чужих документов через ваш сервер.

Можно ли ограничить, кто может грузить файлы, если пока не хочется настраивать встроенную авторизацию?

Да, временный вариант — Basic Auth или allowlist по IP на уровне nginx перед контейнером, пока не настроена штатная система входа приложения.

Сколько памяти закладывать под сервер, если планируется активная работа с OCR и конвертацией?

Ориентируйтесь минимум на 2 ГБ RAM для нерегулярной работы с небольшими файлами и от 4 ГБ, если OCR и конвертация Office-документов идут постоянно и файлы объёмные — точную цифру всё равно стоит проверить на своих типовых документах, а не брать по чужому опыту.

Почему после обновления образа перестал работать язык OCR, который раньше был?

Некоторые релизы меняют способ поставки языковых пакетов (докачка при старте вместо встроенных файлов) — проверьте содержимое /usr/share/tessdata внутри контейнера после обновления и при необходимости пересоздайте его с явно заданной переменной LANGS.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →