nodbox
Разделы документации

Настройки сборки и свой Dockerfile

Команды сборки и запуска, корневая папка монорепозитория, версия рантайма, переменные сборки и свой Dockerfile, если автоопределения мало.

Платформа сама выбирает, как собрать приложение из исходников, а семь полей приложения позволяют этот выбор поменять: сборщик, корневая директория, команды сборки и запуска, версии рантайма и два набора переменных сборки. Если в корне сборки лежит Dockerfile, платформа собирает образ по нему, и писать для этого ничего не нужно.

Настройки сборки есть у приложений из репозитория и из архива. У приложения из готового образа сборки нет, и любое из этих полей отвечает ошибкой 422. Меняются настройки через API: на странице приложения в панели их нет.

Что настраивается

Поле Что делает По умолчанию
builder выбирает способ сборки: auto, railpack или dockerfile auto
root_directory каталог внутри репозитория или архива, из которого идёт сборка корень
build_command команда сборки вместо той, что выбрала платформа выбирает платформа
start_command команда запуска вместо той, что выбрала платформа выбирает платформа
runtime_versions версии языков и инструментов, которые нужны сборке выбирает платформа
build_env переменные, видные только сборке пусто
build_secrets секреты, видные только сборке пусто

Автоопределение языка, зависимостей и команды запуска разбирает страница Сборка без Dockerfile. Здесь только то, чем его можно переопределить.

Как изменить настройки

Поля задаются при создании приложения в теле запроса POST /api/v1/applications и меняются запросом PATCH /api/v1/applications/{id}. Правится ровно то, что прислано, остальное остаётся как было. Все запросы и права токена описаны в разделе API nodbox.

Пример для приложения из монорепозитория:

{
  "root_directory": "apps/web",
  "build_command": "pnpm --filter web build",
  "start_command": "node dist/server.js",
  "runtime_versions": { "node": "22" },
  "build_env": { "NODE_ENV": "production" },
  "build_secrets": { "NPM_TOKEN": "значение секрета" }
}

Текущие значения лежат в блоке build ответа GET /api/v1/applications/{id}. Ключи в нём те же, что в запросе.

Настройки действуют со следующей версии

Правка настроек ничего не деплоит. Она ложится на приложение, а каждая новая версия снимает настройки в момент заказа и собирается по этому снимку. Работающая версия остаётся такой, какой была.

Из этого следует два правила:

  • Новые настройки заработают, когда закажешь версию или запушишь в ветку с включённым автодеплоем.
  • Версия, которая уже собирается, не заметит правку, сделанную после её заказа.

Откат возвращает версию с уже собранным образом, поэтому сборка при откате не повторяется. Подробнее - в разделе Версии и откат.

Чем собирать: поле builder

Поле builder решает, чем собирать образ.

Значение Что происходит
auto есть Dockerfile в корне сборки - образ собирается по нему, нет - платформа определяет язык сама
railpack образ собирает платформа, даже если Dockerfile лежит рядом: он может быть нужен только для локальной разработки
dockerfile образ всегда собирается по Dockerfile; если файла нет, версия падает с причиной dockerfile_missing

Явный dockerfile не уходит в автоопределение молча: выбранный способ платформа не подменяет другим. Что именно выбрано, видно в начале лога сборки. Например, при auto там будет строка «В корне сборки найден Dockerfile - образ собирается по нему.»

Команды сборки и запуска и версии рантайма действуют только в сборке, которую ведёт платформа. Если образ собирается по Dockerfile, всё это записано в самом файле. Поэтому при builder: dockerfile поля build_command, start_command и runtime_versions запрещены: запрос с ними отвечает 422. Платформа судит тот сборщик, который будет у приложения после запроса. Запрос {"builder": "railpack", "build_command": "make"} для приложения с Dockerfile проходит, а {"builder": "dockerfile", "build_command": "make"} нет.

Переход на dockerfile ранее заданные команды и версии не стирает: они вернутся в дело вместе с автосборкой. Стереть их можно явно: null для команд и {} для версий. Если при auto команды заданы, а Dockerfile найден, в логе сборки появится строка о том, что они не применяются.

Монорепозиторий: корневая директория

Поле root_directory задаёт каталог, из которого идёт сборка. Для приложения из монорепозитория это apps/web или другой путь до его папки с package.json или Dockerfile. Всё, что лежит выше этого каталога, сборке не видно: он становится её контекстом.

Правила записи пути:

  • путь считается от корня репозитория или архива, без ведущего слэша
  • . и .. в пути запрещены
  • завершающий слэш отбрасывается: apps/web/ и apps/web - один и тот же каталог
  • пустое значение или null возвращают сборку из корня

Каталога может не оказаться в исходниках версии, или путь может вести через символическую ссылку за их пределы. В обоих случаях версия падает с причиной root_directory_missing, а лог сборки просит проверить путь в настройках. Если указан root_directory, то и Dockerfile ищется в нём, а не в корне репозитория.

Для автодеплоя монорепозитория есть отдельный фильтр путей: Автодеплой по push. Корневая директория выбирает, что собирать, а фильтр - при каких изменениях запускать сборку.

Команды и версии рантайма

build_command и start_command переопределяют выбор платформы. Это одна строка для оболочки, до 512 символов и без управляющих символов вроде перевода строки. Пустая строка и null значат «пусть решает платформа».

{
  "build_command": "npm run build:prod",
  "start_command": "node dist/server.js"
}

runtime_versions - объект вида «имя инструмента: версия». Платформа не знает язык приложения до сборки, поэтому версия указывается вместе с именем инструмента:

{
  "runtime_versions": { "node": "22", "python": "3.12" }
}

Инструментов не больше десяти. Имя пишется строчными латинскими буквами, цифрами и дефисом, начинается с буквы. Версия - это строка вроде 22, 3.12 или 1.22.5, без пробелов и знака @. Набор заменяется целиком: присланный объект и есть новый набор, {} возвращает выбор платформе.

Переменные сборки и переменные приложения

У приложения четыре набора переменных, и они не пересекаются. Переменная сборки не попадает в работающее приложение, а переменная приложения не видна сборке.

Набор Кто видит значение Что отдаёт API
env работающее приложение значения
secrets работающее приложение только имена
build_env сборка значения
build_secrets сборка только имена

Пара env и secrets описана на странице Переменные и секреты. Одно и то же имя, например NODE_ENV, можно задать и в env, и в build_env с разными значениями: это две настройки двух разных этапов.

Правила у build_env и build_secrets такие же, как у рантаймовых наборов:

  • имя состоит из латинских букв, цифр и подчёркивания и не начинается с цифры
  • имя не длиннее 128 символов, значение не длиннее 4 096 символов
  • переменных и секретов сборки вместе не больше 100
  • одно имя не может быть одновременно в build_env и в build_secrets: запрос отвечает 422 с названием имени
  • несколько системных имён, например PATH и HOME, заняты платформой, и ответ 422 называет такое имя

Правятся наборы по-разному:

  • build_env заменяется целиком. Присланный объект и есть новый набор, {} убирает все переменные, а если поле не прислать, набор не тронут.
  • build_secrets накладывается поверх прежнего набора. Присланное имя получает новое значение, null под именем стирает секрет, неназванные остаются. Пустая строка - это значение, а не удаление.

Значения секретов сборки наружу не возвращаются никогда: по API в блоке build лежит список имён. Поэтому прислать набор целиком было бы нечем. Чтобы превратить переменную сборки в секрет, одним запросом пришли build_env без неё и build_secrets с ней.

В автосборке значения обоих наборов доступны командам сборки. В Dockerfile между ними есть разница, она разобрана ниже.

Свой Dockerfile

Положи файл с именем Dockerfile в корень сборки, и при builder: auto образ соберётся по нему. Корень сборки - это корень репозитория или архива, а если задана root_directory, то этот каталог.

Что ожидает платформа

  • Файл называется ровно Dockerfile, с заглавной буквы. Имена dockerfile, Containerfile и Dockerfile.prod платформа не подхватывает, как и файл не в корне сборки. При auto она в этом случае определит язык сама, а при dockerfile версия упадёт с dockerfile_missing.
  • Команду запуска платформа берёт из самого Dockerfile, из CMD или ENTRYPOINT: в настройках приложения она при этом запрещена.
  • Образ может работать от root. Права внутри контейнера те же, что в обычном контейнере Docker, кроме отправки сырых сетевых пакетов.
  • Порт веб-приложения платформа берёт из настройки приложения, а не из строки EXPOSE. Слушай тот порт, который указан в настройках, он же передаётся в переменной PORT. Подробнее - в разделе Порт, протокол и проверка готовности.
  • Сборка идёт до 16 минут, потом платформа её останавливает. Образ, который не помещается в лимит, закрывает версию причиной image_too_large.

Контекст сборки

Контекстом служит корень сборки целиком. Пути в COPY и ADD считаются от него, и файлы выше него недоступны. У приложения из монорепозитория поэтому задай root_directory: "apps/web" и копируй пути относительно apps/web, а не от корня репозитория.

Переменные в Dockerfile

Переменная сборки приходит аргументом, секрет сборки приходит только монтированием в шаг RUN:

FROM node:22-alpine
WORKDIR /app

ARG VITE_API_URL
COPY package*.json ./
RUN npm ci

COPY . .
RUN --mount=type=secret,id=SENTRY_AUTH_TOKEN \
    SENTRY_AUTH_TOKEN="$(cat /run/secrets/SENTRY_AUTH_TOKEN)" npm run build

CMD ["node", "dist/server.js"]

Здесь VITE_API_URL берётся из build_env и читается строкой ARG, а SENTRY_AUTH_TOKEN из build_secrets доступен только этому шагу RUN. В слои образа секрет не попадает. Значение ARG остаётся в истории образа, поэтому ничего секретного в build_env класть нельзя. Переменные приложения из env и secrets при сборке не видны, а переменные сборки не попадают в работающее приложение: если значение нужно и там, и там, задай его в обоих наборах.

Что учесть при сборке

  • Кэша слоёв между сборками нет: каждая сборка идёт с нуля. Шаг RUN --mount=type=cache работает, но кэш в нём при каждой сборке пустой.
  • Из сборки открыт интернет: RUN может скачивать пакеты и файлы.
  • Базовый образ в FROM должен быть публичным: логина к закрытым реестрам у сборки нет. Образы с Docker Hub и GitHub Container Registry платформа держит рядом со сборкой, поэтому они скачиваются быстрее.
  • Выбрать стадию многостадийной сборки через --target и указать другой путь к Dockerfile нельзя: таких настроек у приложения нет.

Если сборка не прошла, причина и строка, на которой она сломалась, видны в логе сборки. Частые отказы и что с ними делать - на странице Типичные сбои и что делать.

Что дальше


Страница в markdown, так её читает агент: /docs/deploy/build-settings.md