Скоро я запускаю интерактивный плеер кода (как уроки в Ютубе, только вы всегда имеете доступ к коду в любой промежуток времени) в браузера. Одной из фич моей платформы — возможность запускать написанный код. Урок или свой опыт человек может записать на любом языке, потому мне остро понадобился универсальный Sandbox для любого языка, желательно с возможностью запускать код из нескольких файлов.

Кроме того не хотелось бы платить за запросы в имеющиеся платформы. А также нужна возможность управлять (добавлять/менять) новые технологии быстро, не платить за запросы имеющимся платформам. Кроме того хотелось наконец выпустить что-то полезное в своем гитхабе и иметь строчку в резюме.

Что есть из доступного

На самом деле решений не так много. Основной провайдер таких услуг — проект Judge0. Песочница всем классная: поддерживает десятки языков, изоляция сделана на базе isolate, ограничивая linux cgroup/permissions. Но я столкнулся с его минусами:

  • Старый и редко обновляется последнее время. До банального — языки старых версий

  • Сложный запуск кода из нескольких файлов. Платформа Judge0 позволяет это делать, но крайне не удобно

  • Довольно скудные возможности настраивать каждую технологию, на этой платформе банально добавлен огромный список бинарников и не учитываются особенности каждого языка. Например TypeScript запускается без tsconfig и банально нельзя использовать типы вида Foo[] или Array<Foo>. Примеров для других языков нет, но они возможны

  • При всей простоте Judje0, сделан он инфраструктурно сложно: Руби приложение, БД для хранения стейтов. Руби я не знаю, стейт не нужен для хранения или он будет организован сторонними силами, на платформе запуска это мне оказалось не нужным

  • Надо платить за имеющийся вариант АПИ или разворачивать и много дорабатывать

На рынке есть плейграунды для отдельных языков. Например, для Golang есть опенсорсный для go — сделан круто, но только один язык.

Есть у JetBrians для языка Kotlin, тоже крутой, но тоже ограничен одной платформой.

Делаем свое

Мне очень понравился вариант песочницы у Google для Go. Суть ее работы сводится к тому, что есть веб-сервис, который компилирует go код, далее он отправляет по приватной сети на машину, в которой запрос принимает веб-сервис, запущенный в докер с привилегированным доступом к докеру хоста и плодит sandbox-контейнеры с го, передавая через stdin скомпилированный бинарный код. Так у сервиса есть доступ к докеру хоста, то для изоляции используется технология Google gVisor.

С этими вводными и на базе этой кодовой базе я и решил реализовать свое решение, но уже универсальное по части языков. Поехали!

Итоговая схема работы примерно такая, как у гугла:

Общая схема работы проекта
Общая схема работы проекта

Так как код может быть любым на любом языке, не только Golang код, то у первого Playground сервиса убирается ответственность по компиляции кода и переезжает в сервис на Sandbox машине, там отдельным вызовом она будет делать еще один вызов внутри контейнера.

Сами sandboxes теперь тоже не го, потому мы должны предоставить образы машине, в которых будет обрабатываться входной код. Так как это докер-сервис, то просто передадим папку с конфигами — все очень тупо и просто.

Схема поставки конфигов:

Второй путь (через АПИ) пока только в планах в виде набросков, но скоре будет реализован.
Второй путь (через АПИ) пока только в планах в виде набросков, но скоре будет реализован.

Конфигурация образа простая — это набор из докерфайла с нужным языком, и json конфиг с данными команды по запуску кода, а также алиас/код, по которому мы будет определять что код нужно запустить реквест именно в контейнере этого образа.

В целом это все. Под капотом еще внедрены хуки через go-plugin, для случаев, например, таких, когда какой-то язык мы хотим обработать на другом сервисе, а не через ресурсы нашего Sandbox. Или для организации Authentication, для хранения (пока тоже в виде набросков, тк реализован полноценно только PreRequest хук, ответы от обработчиков хуков еще не реализованы).

Проблемы

Есть проблемы с этапом компиляции. Для него нужна сеть, а контейнеры создаются в приватном докерном рантайме gVisor без сети ( —network=none) и с ограничением памяти. Потому на данном этапе нельзя собрать проект с пакетными зависимостями... Буду рад вашим предложениям как это организовать.

Также нет возможности переиспользовать стейт песочницы (то есть нельзя иметь некоторую сессию) — также рад буду вашему участию и предложениям.

Ссылка

Проект еще сырой (MVP-код без тестов), пока не особо протестирован и не имеет кучу фич. Но уже можно запускать и играться. Буду рад вашим отзывам.

https://github.com/codiewio/codenire

Комментарии (6)


  1. alhimik45
    23.01.2025 15:26

    Интересно, а вариант запускать прям в браузере через https://webvm.io/ или аналог не подходит?


    1. Maksclub Автор
      23.01.2025 15:26

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


      1. alhimik45
        23.01.2025 15:26

        Я имел в виду не чистый WebAssembly, а именно использование in browser эмулятора линукса, чтобы там уже запускать то же самое, что запускается в контейнерах на стороне сервера


        1. Maksclub Автор
          23.01.2025 15:26

          Спасибо! Надо поизучать возможности


  1. emilagamamedov
    23.01.2025 15:26

    а что за интеркативный плеер? озадачил ты меня


    1. Maksclub Автор
      23.01.2025 15:26

      Оу... Это платформа, на которой могу писать код и записывать со звуком, потом воспроизводить и можно перематывать на любой момент, переключать файлы в любое время и видеть какое состояние было в тот момент, комментировать с привязкой к коду (строка, время)