#Dev-контейнеры
Продвинутый уровень · Факультатив · около 20 минут плюс время запуска · Нужно: Ограничьте автономные запуски · Сверено с Claude Code v2.1.285 (stable) 09.10.2026
#Цель
К концу этого факультатива вы сможете запускать Claude Code внутри dev-контейнера, сохранять вход при пересборке и давать ему работать без присмотра за файрволом.
#Что понадобится
- Для разбора примера: ваша копия шаблона для практики на GitHub и GitHub Codespaces в вашем аккаунте. На компьютер ничего ставить не нужно: dev-контейнер копии сам устанавливает Claude Code.
- Для задания «Ваша очередь»: один из ваших репозиториев без папки
.devcontainer/, с папкой.practice/, подготовленной, как описано в уроке 1 Начального уровня. - Также для задания: Docker, VS Code с расширением Dev Containers (System requirements) и
jqв macOS, Linux или WSL 2. Без Docker выполните разбор примера и самопроверку из раздела «Проверка». - Расход лимита: небольшой. Пока codespace работает, он также расходует вычислительные ресурсы Codespaces вашего аккаунта GitHub, а пока существует — хранилище (GitHub Codespaces billing).
#Идея
Dev-контейнер — это Docker-контейнер, к которому подключается ваш редактор, на вашем компьютере или в облаке вроде GitHub Codespaces. Если в нём работает Claude Code, команды Claude выполняются в контейнере, а его правки попадают в ваш репозиторий. В отличие от песочницы Bash из урока 4 Среднего уровня, которая оборачивает только команды оболочки, контейнер вмещает весь процесс Claude Code: и файловые инструменты, и MCP-серверы, и хуки (Compare sandboxing approaches).
Три части, каждая дополняет предыдущую:
- Claude Code Dev Container Feature добавляет CLI в любой dev-контейнер (Add Claude Code to your dev container).
- Именованный том в
~/.claudeплюсCLAUDE_CONFIG_DIR, указывающий на этот путь, сохраняют ваш вход, когда пересборка стирает домашнюю папку (Persist authentication and settings across rebuilds). - Эталонный контейнер добавляет непривилегированного пользователя и файрвол, который ограничивает исходящий трафик адресами, разрешёнными его скриптом. Документация поддерживает его для запусков без присмотра с
--dangerously-skip-permissions, которые пропускают запросы разрешений (режим bypass); от root CLI этот флаг не принимает (Run without permission prompts, Dev containers).
Внимание
С --dangerously-skip-permissions «dev-контейнеры не мешают вредоносному проекту вынести всё, что доступно внутри контейнера, включая учётные данные Claude Code, хранящиеся в ~/.claude» (Development containers). Расширение Dev Containers в VS Code к тому же переиспользует в контейнере ваши локальные учётные данные Git и пробрасывает запущенный SSH-агент, а эталонный файрвол пропускает GitHub и SSH, так что запуск может ими пушить (Sharing Git credentials with your container). Используйте dev-контейнер только с репозиториями, которым доверяете, и никогда не монтируйте в него секреты хоста вроде ~/.ssh или файлов с облачными учётными данными.
#Разбор примера
- На GitHub откройте
.devcontainer/devcontainer.jsonв своей копии шаблона:
{
"name": "Claude Code practice",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/devcontainers/features/node:1": { "version": "lts" },
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
},
"postCreateCommand": "sudo apt-get update && sudo apt-get install -y bubblewrap socat"
}
Тег :1.0 закрепляет скрипт установки фичи, а не Claude Code: фича устанавливает последний релиз, который затем обновляется сам (Add Claude Code to your dev container). postCreateCommand устанавливает bubblewrap и socat, которые нужны песочнице Bash в Linux (Set up Linux and WSL2).
2. Выберите Code, затем вкладку Codespaces и создайте codespace на main (Creating a codespace for a repository). Он откроется в редакторе, заданном в ваших настройках Codespaces (Setting your default editor for GitHub Codespaces); шаги 3–6 используют VS Code — в браузере или в настольном приложении.
3. В его терминале:
echo "$CODESPACES"; whoami; claude --version
Будут выведены три строки: true (GitHub задаёт CODESPACES в каждом codespace, Default environment variables for your codespace), vscode (непривилегированный пользователь образа, Ubuntu image) и версия, которая может быть новее отметки на этой странице.
4. Запустите claude, войдите и, когда спросит, доверьтесь папке. Если браузер показывает код вместо возврата в терминал, вставьте его в ответ на Paste code here if prompted (Log in to Claude Code). Затем попросите:
Run uname -a and whoami, then tell me which machine you're running on.
Одобрите команду, если Claude спросит. Claude опишет Linux-контейнер, а не ваш компьютер; формулировки у вас будут другими. Выйдите через /exit.
5. Выполните claude auth status --text: вы вошли (CLI commands). Пересоберите: откройте палитру команд (Ctrl+Shift+P или Cmd+Shift+P на Mac), выполните Codespaces: Rebuild Container и выберите Rebuild (Rebuilding the container in a codespace). После переподключения:
claude auth status --text; echo "exit $?"
Вывод заканчивается на exit 1: вход не выполнен. Пересборка сохраняет /workspaces, где лежит ваш репозиторий, и очищает ~/.claude (Persisting data over a rebuild).
6. Остановите codespace: выполните Codespaces: Stop Codespace из палитры команд или выберите Stop codespace в меню ... рядом с ним на github.com/codespaces. Закрытие вкладки браузера его не останавливает (Stopping and starting a codespace).
#Ваша очередь
Задание: поместите один из своих репозиториев в эталонный контейнер с включённым файрволом и закреплённой версией Claude Code. Сохраните вход при пересборке, дайте Claude выполнить одну небольшую задачу без присмотра, затем проверьте результат на своём компьютере.
Шаги документации открывают в контейнере собственный репозиторий Claude Code; чтобы использовать контейнер со своим проектом, скопируйте его папку .devcontainer/ в свой репозиторий и подправьте Dockerfile под инструменты своего проекта (Try the reference container). В новой ветке скачайте три файла из коммита, с которым сверялось это руководство:
git switch -c try-devcontainer
mkdir -p .devcontainer
ref=d945a61bc6346abce607252d5667df8a3bf0461a
for f in devcontainer.json Dockerfile init-firewall.sh; do
curl -fsSL "https://raw.githubusercontent.com/anthropics/claude-code/$ref/.devcontainer/$f" -o ".devcontainer/$f"
done
Критерии приёмки:
- Вы прочитали все три файла до первой сборки.
init-firewall.shвыполняется от root при каждом старте контейнера:devcontainer.jsonзапускает его какpostStartCommand(Dev Container metadata reference), а Dockerfile позволяет пользователюnodeзапускать его черезsudo. - До первой сборки вы добавили
claude.aiиplatform.claude.comв список доменов, которые разрешаетinit-firewall.sh, рядом сapi.anthropic.com: они нужны для входа и обновления входа (Network access requirements). У хостов может быть общий адрес, а скрипт останавливается на первомipset add, встретившем уже добавленный адрес, поэтому в том же цикле заменитеipset add allowed-domains "$ip"наipset add -exist allowed-domains "$ip":-existигнорирует запись, которая уже есть в наборе (ipset). devcontainer.jsonзакрепляет Claude Code: аргумент сборкиCLAUDE_CODE_VERSIONназывает выбранную вами версию, например2.1.285, вместоlatest, аcontainerEnvдобавляет"DISABLE_AUTOUPDATER": "1". Это рецепт из документации: установить фиксированную версию из Dockerfile и отключить автообновление (Enforce organization policy). Три файла с вашими изменениями закоммичены в вашей ветке.- Dev Containers: Reopen in Container собирает и открывает его. Строки
npm warn EBADENGINEв журнале сборки ожидаемы: эталонный образ работает на Node.js 20, а npm-пакет требует 22 или новее, но npm лишь предупреждает, установка завершается иclaudeработает (Install with npm). В его терминале (Ctrl+`)whoamiвыводитnode,claude --version— вашу версию,curl -sS --connect-timeout 5 https://example.comзавершается ошибкой, аcurl -sS --connect-timeout 5 https://api.github.com/zen— успешно. - Вы один раз входите через
claude. После Dev Containers: Rebuild Containerclaude auth statusпо-прежнему завершается с кодом0: эталон монтирует именованный том в/home/node/.claudeи направляет тудаCLAUDE_CONFIG_DIR, а Docker сохраняет том после удаления контейнера (Volumes). - Один запуск без присмотра завершается в терминале контейнера на задаче, которой не нужны инструменты, отсутствующие в образе, например
claude -p "Add a one-line summary of this repository to the top of README.md" --dangerously-skip-permissions --model sonnet --max-turns 10(CLI flags). - В терминале на своём компьютере, после проверок из первого пункта раздела «Осторожно», вы сохраняете
git status --porcelain > .practice/a-dc-status.txt, затем читаетеgit diff, включая.devcontainer/, прежде чем закоммитить или отбросить изменение запуска.
Когда все пункты раздела «Проверка» ниже выполнены, разберите всё:
- В терминале контейнера выполните
claude auth logout(CLI commands). Пока вы не вышли, том конфигурации хранит ваши учётные данные, а том живёт дольше контейнера. - Закройте окно VS Code, подключённое к контейнеру. По умолчанию закрытие останавливает контейнер (
shutdownActionв Dev Container metadata reference). - Удалите контейнер: в Remote Explorer VS Code выберите Containers, затем щёлкните правой кнопкой по контейнеру и удалите его (Managing containers) или выполните
docker rm <container>(docker container rm). - Удалите два тома, имена которых начинаются с
claude-code-config-иclaude-code-bashhistory-:docker volume lsих покажет, аdocker volume rm <name>удалит каждый. Docker не удаляет том, который ещё использует контейнер, поэтому этот шаг идёт после шага 3 (docker volume rm).
#Проверка
Факультатив пройден, когда выполнено всё это:
- На вашем компьютере
git ls-tree --name-only try-devcontainer .devcontainer/показывает три файла, аgit show try-devcontainer:.devcontainer/devcontainer.json | jq -r '.build.args.CLAUDE_CODE_VERSION, .containerEnv.DISABLE_AUTOUPDATER'выводит вашу версию и1. - В контейнере
whoamiвыводитnode,claude --version— вашу версию, запрос кexample.comне проходит, а кapi.github.com/zen— проходит. - В контейнере после пересборки
claude auth status >/dev/null; echo $?выводит0. - На вашем компьютере
.practice/a-dc-status.txtперечисляет файл, изменённый запуском без присмотра. - Самопроверка (не тестируется): в codespace
claude auth statusпосле пересборки завершился с кодом1, и вы можете назвать две вещи, которые контейнер не защищает: всё, что можно прочитать или использовать внутри него, например~/.claudeи проброшенные учётные данные Git, и каждый файл смонтированного проекта.
Если jq сообщает об ошибке разбора, уберите комментарии или висячие запятые, которые вы добавили в devcontainer.json. Если example.com отвечает или api.github.com не отвечает, скрипт файрвола не отработал: выполните в контейнере sudo /usr/local/bin/init-firewall.sh и прочитайте ошибку. Element cannot be added to the set: it's already added означает, что не хватает правки с -exist. Если claude auth status после пересборки завершается с кодом 1, target тома и CLAUDE_CONFIG_DIR в containerEnv должны указывать на один и тот же путь (Persist authentication and settings across rebuilds). Если файл статуса пуст, запуск ничего не изменил, закоммитил своё изменение (git log -1 его покажет) или остановился на --max-turns, что завершается ошибкой (CLI flags): прочитайте, что он вывел, и дайте задачу поменьше, если ему не хватило ходов.
#Осторожно
- С
--dangerously-skip-permissionsClaude может переписать и.devcontainer/, и.git/: это защищённые пути, но режим bypass пишет в защищённые пути без вопросов (Protected paths). Через монтирование изменение попадает на ваш компьютер: следующая пересборка использует.devcontainer/, а git выполняет хуки из.git/hooksили из папки, указанной в.git/config, при командах вродеgit commit(githooks). Прежде чем пересобирать или запускать git на своём компьютере, прочитайте.git/configи просмотрите.git/hooks, затем сравните.devcontainer/со своим коммитом (git log --oneline, затемgit diff <your commit> -- .devcontainer). - Codespace работает, пока вы его не остановите или пока не истечёт тайм-аут, а остановленный всё равно занимает хранилище (Stopping and starting a codespace). Закончив, удалите его из меню ... рядом с ним на github.com/codespaces или командой
gh codespace delete(Deleting a codespace). - Файрвол блокирует исходящий трафик, не разрешённый его скриптом, для всего в контейнере, включая команды Claude. Если проекту нужен другой хост, например PyPI или приватный реестр, добавьте его в список доменов скрипта и пересоберите (Dev containers). Network access requirements перечисляет хосты, которые используют собственные функции Claude Code.
#Что дальше
- Choose a sandbox environment: dev-контейнеры рядом с песочницей Bash, другими контейнерами, виртуальными машинами и облачными сессиями.
- Enforce organization policy: управляемые настройки, встроенные в образ, и почему файл в репозитории не является границей принуждения.
- Explore the .claude directory: что хранит том в
~/.claude, включая учётные данные, настройки и историю сессий.
Источники: Development containers · Choose a sandbox environment · Choose a permission mode · Configure the sandboxed Bash tool · Authentication · Advanced setup · CLI reference · Enterprise network configuration · Claude Code: эталонный dev-контейнер на d945a61 · GitHub: Creating a codespace for a repository, Setting your default editor for GitHub Codespaces, Default environment variables for your codespace, Rebuilding the container in a codespace, Stopping and starting a codespace, Deleting a codespace, GitHub Codespaces billing · VS Code: Developing inside a Container, Sharing Git credentials with your container · Dev Container metadata reference · Образы Dev Container: Ubuntu · Docker: Volumes, docker container rm, docker volume rm · Git: githooks · ipset
Назад к оглавлению Продвинутого уровня · Тема: Разрешения и безопасность · Застряли на уроке?