Как запустить Chrome в докере и не сойти с ума от тормозов
Знакомая история: нужно автоматизировать сбор данных или протестировать веб-приложение, и вы тянете в проект Playwright или Puppeteer. Всё идет хорошо, пока дело не доходит до деплоя. Тут начинаются танцы с бубном вокруг зависимостей Chromium, вечно «отваливающихся» сессий и дикого жора оперативной памяти. А если нужно еще и глазами посмотреть, что там творится внутри контейнера, то настройка VNC превращается в отдельный квест на вечер.
Недавно наткнулся на репозиторий kernel-images. Ребята из команды Kernel решили собрать всё, что нужно для нормальной работы браузерных агентов, в одном месте. По сути, это готовые образы Chrome, которые живут в песочнице и которыми можно рулить удаленно без боли.
Что внутри этого ящика
Проект предлагает не просто «еще один Dockerfile с хромом». Главная фишка здесь — связка Docker и Unikraft (это такая штука для создания микро-виртуалок или юникернелов). Если с докером всё плюс-минус понятно, то юникернелы дают несколько очень приятных бонусов для тех, кто делает AI-агентов или сложные парсеры.
Вот что умеет этот стек:
- Работает с Playwright и Puppeteer через стандартный протокол CDP (Chrome DevTools Protocol).
- Стримит живую картинку из браузера прямо в интерфейс через WebRTC или noVNC. Можно не только смотреть, но и кликать мышкой.
- Умеет записывать видео сессии.
- Если использовать юникернел, браузер уходит в «спячку» при отсутствии активности и просыпается меньше чем за 20 миллисекунд.
Как это пощупать в Docker
Для большинства из нас Docker — самый понятный путь. Ребята подготовили скрипты для сборки и запуска chromium-headful. Это версия с графическим интерфейсом, которая крутится внутри контейнера.
Сборка выглядит стандартно:
cd images/chromium-headful
IMAGE=kernel-docker ./build-docker.sh
IMAGE=kernel-docker ENABLE_WEBRTC=true ./run-docker.sh
После запуска браузер слушает порт 9222. Это входная точка для ваших скриптов.
Подключение кода
Самое классное, что вам не нужно менять логику своих скриптов. Если у вас уже есть код на Playwright, вы просто указываете ему адрес запущенного контейнера.
Сначала получаем URL воркер-сокета (это стандартный шаг для CDP):
const response = await fetch("http://localhost:9222/json/version");
const { webSocketDebuggerUrl } = await response.json();
А потом скармливаем этот URL вашему любимому фреймворку:
// Для Playwright это выглядит так
const browser = await chromium.connectOverCDP(webSocketDebuggerUrl);
// А для Puppeteer так
const browser = await puppeteer.connect({
browserWSEndpoint: webSocketDebuggerUrl,
});
Теперь ваш скрипт управляет браузером, который изолирован в контейнере, а вы можете открыть порт 443 в браузере и смотреть, как там бегает курсор и нажимаются кнопки.
Зачем тут юникернелы
Честно скажу, технология Unikraft может показаться избыточной, если вам нужно просто раз в день зайти на сайт и нажать кнопку. Но если вы строите инфраструктуру для сотен браузерных агентов, всё меняется.
Юникернел позволяет «заморозить» состояние браузера со всеми куками, открытыми вкладками и даже зумом страницы. Когда запросов нет, такая виртуалка почти не ест ресурсы. Как только прилетает сетевой пакет — она мгновенно восстанавливается из снимка (снапшота). В Docker такого добиться гораздо сложнее.
Запись экрана без костылей
Часто в автоматизации нужно сохранить доказательства работы или понять, почему упал тест. В kernel-images встроили простенькое API для записи.
Включаем флаг WITH_KERNEL_IMAGES_API=true при старте и дергаем обычный curl:
# Старт записи
curl http://localhost:10001/recording/start -d {}
# Тут работает ваш скрипт
# Стоп и скачивание mp4
curl http://localhost:10001/recording/stop -d {}
curl http://localhost:10001/recording/download --output result.mp4
Кому это пригодится
Проект точно стоит покрутить, если:
- Вы делаете AI-агентов, которым нужен визуальный фидбек от браузера.
- Вам надоело возиться с настройкой xvfb и VNC в докере.
- Вы хотите организовать ферму браузеров, которые не будут отъедать всю память сервера в простое.
Из минусов — документация пока короткая, и для запуска юникернела придется поставить kraft CLI и немного разобраться в их облаке (или разворачивать свое). Но даже как база для кастомных Docker-образов с Chrome, этот репозиторий — отличная находка.
Попробовать стоит хотя бы ради того, чтобы увидеть, насколько плавно может работать WebRTC-стриминг из контейнера по сравнению с тормозным VNC.
