Сборка завершилась с ошибкой без логов: как получить вывод
Если сборка завершилась с ошибкой без логов, значит, сбой произошёл ещё до запуска самой сборки. Узнайте о четырёх этапах, на которых это может произойти, как отличить их друг от друга и как получить вывод на каждом этапе.
«Сборка завершилась с ошибкой». Ни stack trace, ни ошибки компилятора, вообще никакого вывода. Сборка завершилась с ошибкой без логов — самое бесполезное сообщение, которое может показать платформа. Обычно оно означает вполне конкретную вещь, в которой стоит разобраться: сбой произошёл до запуска компонента, формирующего логи.
Сборка — это не один шаг. Их четыре, и каждый завершается ошибкой по-своему.
Четыре этапа
1. Получение исходного кода. Платформа клонирует репозиторий на указанном ref. 2. Подготовка сборки. Платформа определяет, как выполнять сборку: с помощью Dockerfile, buildpack или обнаруженного framework. 3. Выполнение сборки. Запускаются ваши команды. Только на этом этапе появляется ожидаемый вывод. 4. Упаковка. Результат преобразуется в запускаемый image.
Если логов нет вообще, сбой произошёл на этапе 1 или 2. Сборка не запускалась, поэтому она ничего и не могла вывести.
Этап 1: код не был получен
Признаки — полная тишина и быстрый сбой, обычно менее чем за пятнадцать секунд.
Распространённые причины в порядке частоты:
- Ветка не существует. Сервис настроен на деплой
master, а репозиторий переименовали вmain. Сбой происходит мгновенно, и сообщение почти ничего не объясняет. - Доступ отозван. Токен или установка приложения, которые работали в прошлом месяце, были удалены либо репозиторий переместили в организацию, где выданное разрешение больше не действует.
- Репозиторий закрытый, а подключение больше не действительно. Ситуация аналогична предыдущей: платформа получает 404, а не 403, потому что именно так Git-провайдеры отвечают для недоступных вам закрытых репозиториев.
- Не удаётся получить submodule. Основной репозиторий клонируется, но submodule с SSH URL завершается ошибкой, потому что в build environment нет нужного ключа.
Быстрая проверка: показывает ли платформа hash коммита для неудачного деплоя? Если нет, код не был получен, и содержимое вашего Dockerfile здесь ни при чём.
Этап 2: непонятно, как выполнять сборку
Здесь также будет тишина, потому что команда сборки ещё не выбрана.
- В указанном конфигурацией месте нет Dockerfile.
dockerfilePathуказывает на путь, который был изменён. - Monorepo без root directory. Платформа проверяет корень репозитория, а ваш сервис находится в
apps/api. - Ничего не обнаружено. Нет распознанного manifest, поэтому ни один buildpack не подошёл.
- Dockerfile не удаётся распарсить. Синтаксическая ошибка в строке 1 приводит к сбою до запуска любого layer.
Этап 3: здесь появляются логи
Если вы видите частичный вывод, который внезапно обрывается, значит, вы на этапе 3. Две наиболее распространённые причины связаны не с кодом, а с ресурсами:
Нехватка памяти. Если build-процесс убивает OOM reaper, он не успевает сообщить об этом. Лог просто обрывается посреди шага. Сборки TypeScript, webpack и Vite на больших codebase регулярно сталкиваются с этой проблемой. Верный признак — тот же коммит без проблем собирается на вашем ноутбуке, где памяти больше, чем у builder.
Timeout. Сборка, превысившая лимит платформы, принудительно завершается. Симптом тот же: вывод обрывается, а не заканчивается штатно.
Если сбой происходит достаточно рано, обе ситуации выглядят как «отсутствие логов».
Этап 4: сборка прошла, но результат нельзя упаковать
Редкий и специфичный случай: сборка завершилась успешно, но artefact оказался некорректным. Например, у image нет CMD или ENTRYPOINT, архитектура не совпадает либо image слишком велик для лимита платформы.
Порядок диагностики
# Is there a commit hash? If not, stage 1.
dockup deployments my-project/my-api --json
# Build logs of the latest deployment, streamed as it goes
dockup logs my-project/my-api --build --follow
# The full record, including which stage took how long
dockup status my-project/my-api --json
Поле stageTimings в последнем выводе — самый быстрый способ определить место сбоя. Если деплой потратил 0,4 секунды на clone, а затем завершился ошибкой на этапе 1, причина найдена. Если сборка выполнялась девяносто секунд, а затем остановилась, проблема относится к этапу 3 и, скорее всего, связана с памятью.
Как получить вывод, если его нет
Три приёма в порядке возрастания трудозатрат:
Воспроизведите ограничение локально. Вопрос не в том, «собирается ли проект на моей машине», — соберите его с тем же объёмом памяти, который доступен builder:
docker build --memory=2g --memory-swap=2g -t test .
Если это воспроизводит сбой, причина найдена: дело в памяти, а не в чём-то загадочном.
Сделайте сборку более подробной. Большинство build tools по умолчанию не сообщают о проблеме, которая вот-вот их остановит.
# Print progress so a truncated log still shows where it stopped
RUN npm ci --loglevel verbose
RUN NODE_OPTIONS="--max-old-space-size=3072" npm run build
Одной строки с NODE_OPTIONS уже стоит попробовать: если Node build завершается без вывода, очень часто причина в ограничении heap, и его увеличение исправляет сборки, которые не выдавали вообще никакой диагностики.
Выполните bisect Dockerfile. Закомментируйте всё после проблемного шага и добавьте маркеры RUN echo "reached step N". Метод грубый, но он работает, когда больше ничего не помогает.
Как снизить вероятность таких проблем
Два фактора важнее любых приёмов отладки.
Потоковая передача логов вместо сводных логов. Если вывод появляется только после завершения сборки, принудительно остановленная сборка не выдаст ничего: summary записывается в конце. При потоковой передаче у вас остаётся лог вплоть до момента сбоя.
dockup logs my-project/my-api --build --follow
Именованные этапы с измерением времени. «Сборка завершилась с ошибкой» — это один бит информации. «Clone: 0,4 с, build: ошибка через 94 с» позволяет исключить три из четырёх причин выше, даже не читая остальное.
Часто задаваемые вопросы
Почему моя сборка вообще не выдаёт логов? Потому что сбой произошёл до запуска команд сборки — обычно при получении исходного кода или определении способа сборки. Ни на одном из этих этапов вывод сборки не формируется.
Почему локально сборка проходит, а на платформе — нет?
Чаще всего причина в памяти. На вашей машине её больше, чем у builder. Перед дальнейшей диагностикой проверьте это с помощью docker build --memory=2g.
О чём говорит лог, который обрывается посреди шага? Процесс был принудительно остановлен, а не завершился самостоятельно. Наиболее вероятны нехватка памяти или timeout сборки: OOM killer не даёт процессу возможности объяснить причину.
Нужен ли мне Dockerfile? Не обязательно: платформы умеют распознавать распространённые типы проектов и собирать их без него. Но сбой автоматического обнаружения сам по себе является тихой ошибкой без логов, поэтому явный Dockerfile устраняет целый класс неоднозначностей.
