Skip to content

Code Runner ​

Описание ​

runner-code — раннер для выполнения произвольного кода в изолированной песочнице (Firecracker по умолчанию, либо Docker). Тело задачи (command) — это исходный код; язык и зависимости задаются переменными задачи.

Схема выполнения:

  1. Код записывается в файл (main.py, main.js, ...) во временный workspace на хосте, который доступен в sandbox как /workspace.
  2. Если заданы зависимости — они устанавливаются отдельной стадией с доступом в сеть (install_network, по умолчанию bridge). Зависимости ставятся внутрь /workspace и переживают стадию.
  3. Код запускается без сети (network=none по умолчанию) с лимитами памяти/CPU (Docker дополнительно: pids, --cap-drop=ALL, no-new-privileges).
  4. Файлы, записанные кодом в $ARTIFACT_DIR (/workspace/artifacts), автоматически загружаются в storage платформы.

Поддерживаемые языки ​

ЯзыкАлиасыОбраз по умолчаниюФайл кодаЗависимости
pythonpy, python3python:3.12-slimmain.pypip (CODE_DEPS, CODE_DEPS_FILE = requirements.txt)
nodejs, javascript, nodejsnode:22-alpinemain.jsnpm (CODE_DEPS, CODE_DEPS_FILE = package.json)
typescripttsnode:22-alpinemain.tsnpm (как node), запуск через --experimental-strip-types
gogolanggolang:1.24-alpinemain.gogo get + go mod tidy (CODE_DEPS_FILE = go.mod)
rubyrbruby:3.3-slimmain.rbgem install (CODE_DEPS)
php—php:8.3-climain.phpне поддерживаются
bashsh, shellalpine:3.20main.shapk-пакеты; ставятся в том же контейнере, поэтому запуск идёт с сетью

Конфигурация ​

Общие параметры runner-common ​

См. Общая документация.

Специфичные параметры ​

Параметр (config)EnvФлагПо умолчаниюОписание
runtimeCODE_RUNTIME-runtimefirecrackerBackend: firecracker | docker
docker_hostDOCKER_HOST-docker-hostиз окруженияХост docker daemon (runtime=docker)
pull_policyCODE_PULL_POLICY-pull-policyif-not-presentalways | if-not-present | never (docker)
default_languageCODE_DEFAULT_LANGUAGE-default-language—Язык, если задача не задала CODE_LANGUAGE
networkCODE_NETWORK-networknoneСеть на стадии запуска кода
install_networkCODE_INSTALL_NETWORK-install-networkbridgeСеть на стадии установки зависимостей
memoryCODE_MEMORY-memory512mЛимит памяти
cpusCODE_CPUS-cpus1.0Лимит CPU
pids_limitCODE_PIDS_LIMIT-pids-limit256Лимит pids (runtime=docker)
userCODE_USER-userиз образаПользователь контейнера (runtime=docker)
upload_artifactsCODE_UPLOAD_ARTIFACTS-upload-artifactstrueЗагрузка артефактов из /workspace/artifacts
images——см. таблицу языковDocker-образы по языкам
firecracker_binCODE_FIRECRACKER_BIN-firecracker-binfirecrackerПуть к бинарнику Firecracker
kernel_pathCODE_KERNEL_PATH-kernel-path—Guest kernel (vmlinux), обязателен для Firecracker
rootfs_dirCODE_ROOTFS_DIR-rootfs-dir—Каталог {language}.ext4
rootfs———Карта language → путь к .ext4
cni_network_nameCODE_CNI_NETWORK_NAME-cni-network-name—CNI-сеть для стадий с сетью ≠ none
cni_conf_dirCODE_CNI_CONF_DIR-cni-conf-dir/etc/cni/net.dКаталог CNI conf
cni_bin_dirCODE_CNI_BIN_DIR-cni-bin-dir/opt/cni/binКаталог CNI plugins

Firecracker rootfs должен содержать /sbin/unishift-agent (см. runners/code/guest/unishift-agent, скрипт runners/code/scripts/prepare-rootfs.sh). На macOS / без KVM: runtime: docker.

Пример YAML ​

yaml
url: "https://app.com/"
token: "your-token"
concurrency: 2
tags: "code,sandbox"
description: "Sandboxed code executor"

runtime: firecracker
kernel_path: /var/lib/unishift/firecracker/vmlinux
rootfs_dir: /var/lib/unishift/firecracker/rootfs
default_language: python
network: none
install_network: bridge
memory: 512m
cpus: 1.0

Docker (local):

yaml
runtime: docker
default_language: python
network: none
install_network: bridge
memory: 512m
cpus: 1.0
pids_limit: 256
images:
  python: "my-registry/python:3.12-slim"

Переменные задачи ​

ПеременнаяОписаниеПример
CODE_LANGUAGEЯзык кода (обязательна, если нет default_language)python
CODE_DEPSСписок зависимостей (через запятую/пробел/перенос строки)requests, pandas
CODE_DEPS_FILEСодержимое нативного файла зависимостей (requirements.txt / package.json / go.mod)requests==2.32.0
CODE_IMAGEПереопределение docker-образаpython:3.13-slim
CODE_NETWORKПереопределение сети стадии запускаbridge
CODE_UPLOAD_ARTIFACTSВключить/выключить загрузку артефактовfalse

Все переменные задачи (включая служебные CODE_*) также передаются в контейнер запуска как переменные окружения.

Примеры задач ​

Python с зависимостями ​

command: |
  import requests_mock  # доступен: установлен на стадии deps
  print("ok")
variables:
  - { name: CODE_LANGUAGE, value: python }
  - { name: CODE_DEPS, value: requests-mock }

Точные версии через requirements.txt ​

variables:
  - { name: CODE_LANGUAGE, value: python }
  - name: CODE_DEPS_FILE
    value: |
      requests==2.32.3
      pydantic>=2,<3

Node/TypeScript ​

command: |
  import { z } from "zod";
  console.log(z.string().parse("hello"));
variables:
  - { name: CODE_LANGUAGE, value: ts }
  - { name: CODE_DEPS, value: zod }

Go ​

command: |
  package main

  import (
      "fmt"
      "github.com/google/uuid"
  )

  func main() { fmt.Println(uuid.NewString()) }
variables:
  - { name: CODE_LANGUAGE, value: go }
  - { name: CODE_DEPS, value: github.com/google/uuid }

Артефакты ​

Код пишет файлы в директорию из переменной окружения ARTIFACT_DIR (всегда /workspace/artifacts):

python
import os
out = os.environ["ARTIFACT_DIR"]
with open(os.path.join(out, "report.csv"), "w") as f:
    f.write("a,b\n1,2\n")
  • Артефакты загружаются только при успешном выполнении (код возврата 0)
  • Загружаются все файлы из ARTIFACT_DIR (рекурсивно, с сохранением структуры)
  • artifact_id возвращается в статусе задачи

Передача переменных окружения ​

Переменные задачи передаются в контейнер запуска как env:

variables:
  - { name: CODE_LANGUAGE, value: python }
  - { name: API_MODE, value: staging }
python
import os
print(os.environ["API_MODE"])  # staging

Песочница ​

  • Сеть стадии запуска — none (полная изоляция; переопределяется CODE_NETWORK / конфигом)
  • --cap-drop=ALL, --security-opt no-new-privileges
  • Лимиты: память (512m), CPU (1.0), pids (256)
  • Файловая система хоста недоступна — монтируется только временный workspace
  • Workspace удаляется после выполнения
  • Таймаут задачи (task_timeout) останавливает контейнер

Замечания:

  • Для bash зависимости (apk) ставятся в контейнер, поэтому при наличии CODE_DEPS запуск идёт с сетью.
  • Стадия установки зависимостей имеет доступ в сеть — не передавайте секреты в задачи с недоверенными зависимостями.

Обработка ошибок ​

  • Ненулевой код возврата → статус failed с текстом Code failed with exit code N
  • Ошибка установки зависимостей → failed (стадия запуска не выполняется)
  • Неизвестный язык / неподдерживаемые зависимости → failed с пояснением
  • Таймаут контекста → контейнер останавливается, статус failed

Остановка ​

Корректно обрабатывает SIGINT и SIGTERM. Запущенные контейнеры останавливаются и удаляются.