Docker agent: песочница для AI-агентов выключена по умолчанию
Docker Desktop обновился до версии 4.63, и вместе с обновлением на машины разработчиков приехала новая команда: docker agent. Никакого анонса, который надо было специально прочитать. Среда для AI-агентов поставляется предустановленной и появляется сама, как когда-то docker compose. Инженер Сэм Лаббе разобрал её репозиторий и документацию за один вечер, и его вывод умещается в одну фразу: инженерно стена сделана хорошо, а история не в этом. История в дефолтах.
Если коротко, Docker привёз среду, в которой агент описывается YAML-конфигом, подключается к любому MCP-серверу и может запускаться в изолированной виртуалке с сетью default-deny. Всё это уже лежит на диске у миллионов разработчиков. Единственная деталь, которую нужно знать: защитная песочница по умолчанию выключена.
Что на самом деле поставил Docker
Официальное описание звучит так: «собирай, запускай и делись AI-агентами через декларативный YAML-конфиг». По сути это модель конфигурации Claude Code, переведённая в конфиг: агент становится файлом, а не кодом. Блок toolsets объявляет, что агенту доступно: type: filesystem, type: shell и type: mcp для серверов из каталога Docker. В документации речь о сотнях MCP-серверов, подключаемых строкой ref: с указанием на локальный, удалённый или докеризованный сервер.
Из провайдеров поддержаны OpenAI, Anthropic, Gemini, Bedrock, Mistral, xAI и собственный Docker Model Runner. В комплекте страница про permissions, гайд по секретам и трейсинг через OpenTelemetry. Лицензия Apache 2.0, больше десяти тысяч коммитов, анонимная телеметрия. Docker, если что, используют этот инструмент для сборки самих себя.
С точки зрения политики доступа здесь правильная инверсия: вместо списка запрещённого агент получает список разрешённого, а всё неперечисленное отваливается по умолчанию. Поверхность инструментов, описанная в diffable-YAML, ревьюится в пул-реквесте, и это на голову лучше, чем hook-скрипты, которые обычно городит каждый вокруг своего кодинг-агента в одиночку.
Практически это значит, что среды для агентов перестают быть отдельным классом продуктов, который надо ставить руками. Они встраиваются туда, где уже находится код, в докер, который стоит у каждого, кто пишет или запускает софт.
Почему это разговор про безопасность
Вся конструкция стоит на одной линии разлома: между тем, что агент может прочитать, и тем, что ему разрешено делать. Пока запуск идёт на хосте, type: shell и type: filesystem означают ровно то, что означали всегда: права твоей учётной записи и есть радиус поражения. А ноутбук разработчика это плохое место для автономного процесса. Там SSH-ключи, облачные креды, .env с боевыми секретами и доступ к внутренним сетям.
Жанр историй «мой агент удалил базу данных» давно стал мемом, а на соседнем dev.to недавно описали случай, где агент через MCP-права удалил все контейнеры на машине. Docker контекст знает и построил стену. Вопрос только в том, где именно она стоит и от кого заперта.
Стена, как её спроектировали
Песочница это не просто контейнер. Агент запускается внутри Docker Sandboxes VM с отдельной CLI-обвязкой, и таблица монтирований описана явно: рабочая директория подключается на чтение-запись, конфиг агента и директории kit на чтение, всё остальное хосту не видно, дословно «other host files are not visible to the agent». У виртуалки собственный $HOME, так что домашняя директория с ключами остаётся снаружи.
Сеть закрыта по принципу default-deny: исходящий трафик идёт через прокси, который по умолчанию пропускает только шлюз модели и реестры пакетов из пер-ранового allowlist. Расширяется это через runtime.network_allowlist в конфиге или персистентную команду docker agent sandbox allow. Именно этот элемент закрывает главный сценарий: если агент поймал prompt injection, канал эксфильтрации умирает на прокси, что бы модель себе ни решила. Облачный режим включает песочницу неявно и отказывается загружать API-ключи с хоста.
Находка: --sandbox по умолчанию false
А теперь то, ради чего стоит читать разбор целиком. У флага --sandbox дефолт false. Включить можно тремя путями: явным флагом на конкретный запуск (docker agent run --sandbox agent.yaml), в YAML через runtime.sandbox: true, или привязав к алиасу, которым команда реально пользуется. Каждый из путей требует, чтобы кто-то прочитал документацию и принял сознательное решение. А запуск без флагов работает на хосте, где type: shell и type: filesystem означают твою учётную запись в качестве радиуса поражения.
Дефолты это политика. Каждый инструмент, который прячет безопасный режим за флагом, ставит на то, что пользователи читают документацию, а весь жанр «агент удалил базу» это летопись данной ставки. Удобство не является уязвимостью, но именно удобство решает, будет ли уязвимость востребована: каталог MCP-серверов делает подключение мощного инструмента одним кликом в YAML, а ревью агентского конфига у большинства заканчивается на именах в блоке toolsets.
У opt-in есть и легитимная логика. Максимальная изоляция ломает часть сценариев: агенту бывает нужен доступ к файлам вне рабочей директории, к GitHub или к внутренним сетям, и продукт, включивший всё по умолчанию, получил бы поток жалоб в первый же день. Но эта логика конфликтует с тем, как дефолтные конфиги живут в реальности: их копируют, не читая.
Три двери, которые не закрываются
Даже с включённой песочницей остаются три двери, и документация честна как минимум насчёт первой.
Цепочка поставок инструментов это цепочка поставок контекста. Изоляция ограничивает то, что код делает, а tool poisoning атакует то, что модель читает. MCP-сервер внутри идеально изолированной VM всё равно возвращает описания инструментов, и эти описания модель потребляет как контекст. Таблица монтирований не фильтрует текст. В обсуждении под разбором автор предлагает конкретную защиту: фиксировать ответ listTools хэшем в момент регистрации, на каждом старте сессии сравнивать отдаваемые определения с этим baseline и показывать изменение как находку, а не молча подхватывать. Пиннинг образов эту дыру не закрывает: digest уверенно указывает на то, что опубликовал издатель, включая malware, а описания инструментов к тому же генерируются в рантайме и зависят от конфига и окружения.
Редакция секретов работает best-effort, по собственным словам Docker: автоматическая редакция kit может пропустить обфусцированные токены. Вместе с тем, что остановленные песочницы никогда не удаляются автоматически, это означает, что токены могут жить в остановленном состоянии до ручного sbx rm --force. Такие песочницы вдобавок могут продолжать тарифицироваться за хранение.
Третья дверь это mutable-теги: они ломают воспроизводимость, и доки сами советуют пинить удалённые kit и образы по digest. Совет правильный, но нигде не дефолт.
И один слой отсутствует целиком. Трейсы OpenTelemetry отвечают на вопрос, что произошло, но пишутся в подконтрольный тебе коллектор в формате, который нельзя подписать. Трейс это история для отладки, а аудиту нужна запись, о которой можно доказать, что её никто не редактировал. Такого слоя нет ни здесь, ни у кого-то ещё из мейнстрима.
Почему кейс важнее одного продукта
История выходит за пределы Docker. Агентские рантаймы уже приезжают к пользователям по умолчанию: в редакторах кода, в терминалах, в CI, а теперь и в Docker Desktop. Защита при этом почти всегда приезжает опцией. Это не заговор, а продуктовая логика: строгая изоляция мешает типовым сценариям, а типовые сценарии это то, за что платят. Проблема в том, что дефолтный конфиг живёт по другим законам, чем пресс-релиз: его копируют из README соседнего проекта и не читают.
Через год агентская безопасность будет измеряться не качеством моделей, а тем, что включено у всех по умолчанию. Разбор Docker показывает, как выглядит первый шаг этой гонки: хорошая инженерия, отличная документация и рубильник, который ждёт, пока кто-то прочитает доки.
Что сделать прямо сейчас
Если у тебя Docker Desktop 4.63 или выше, команда уже установлена, проверь через docker agent --help. Включай песочницу заранее: гоняй через docker agent run --sandbox agent.yaml, а ещё лучше пропиши runtime.sandbox: true прямо в YAML, чтобы защита переживала копипаст конфига между командами. Третий вариант, привязка к алиасу (docker agent alias add safe-coder myorg/coder --sandbox), пригодится там, где агента запускают десятки раз в день и флаг рано или поздно забудут.
Дальше гигиена. Пинить удалённые образы и kit по digest, чистить остановленные песочницы (docker agent sandbox ls, затем sbx rm --force), не выпускать конфиг, в котором type: shell и type: filesystem соседствуют без ревью, и читать определения инструментов MCP как код, потому что кодом они и являются.
Из комментариев стоит забрать ещё одно правило: пин предлагает конфиг, а подтверждает решение процесс, отличный от предлагающего. Это разделение обязанностей защищает от самоподтверждения, когда один и тот же автор пишет и пин, и суждение о нём.
Часто задаваемые вопросы
Что такое docker agent и откуда он взялся?
Это команда запуска AI-агентов внутри Docker Desktop начиная с версии 4.63. Агенты описываются декларативным YAML-конфигом, подключают MCP-серверы и любого из популярных провайдеров моделей. Отдельно ставить ничего не нужно: команда поставляется предустановленной, а Docker использует её для сборки собственных продуктов.
Это опасно, если оставить песочницу выключенной?
Да, если агент запускается на хосте. Права твоей учётной записи становятся радиусом поражения: агент читает и пишет файлы, ходит в сеть и выполняет shell-команды. Prompt injection или обычная ошибка модели превращаются в полноценный инцидент. Включай --sandbox до первого запуска, а не после первого сюрприза.
Почему default-deny egress называют главным куском?
Потому что он закрывает эксфильтрацию независимо от решений модели. Даже из идеально изолированного окружения один «полезный» curl может вынести данные наружу. Прокси с запретом по умолчанию убивает этот путь на уровне сети, а разрешения выдаются явным allowlist под конкретный запуск.
Итог
Лаббе честно оговаривает два ограничения своей работы. Первое: это чтение исходников и документации, а не тестирование, и доверие к докам это предположение, которое он им одалживает; разрыв между документацией и поведением это ровно то место, где он ловил обходы собственной защиты. Второе: у критики есть срок годности, потому что Docker может переключить дефолт одним релизом и сделать его заголовок устаревшим лучшим из возможных способов.
А пока всё просто. Проверь версию Docker Desktop, загляни в docker agent --help и включай песочницу до первого запуска, а не после инцидента. И держи в голове главное: дефолты решают, а не документация. Если тему изоляции агентов хочется глубже, на блоге уже были разборы того, как агенты останавливаются на полпути и почему аудит их действий до сих пор не решён.