Konfiguracja kontenera deweloperskiego dla Claude Code
ENDev container dla Claude Code to plik .devcontainer/devcontainer.json w repozytorium, który instaluje Claude Code przez oficjalny Dev Container Feature Anthropic, dzięki czemu każde polecenie Claude’a wykonuje się w identycznym, odizolowanym środowisku, a nie na hoście. Konfiguracja zespołowa dodaje wolumen utrzymujący logowanie, politykę zarządzaną, firewall ruchu wychodzącego i test dymny w CI.
Nowa osoba dołącza w poniedziałek i traci dwa dni na wersje Node’a, lokalnego PostgreSQL-a i zmienną proxy, której nikt nie spisał. W tym samym czasie ktoś z zespołu uruchamia Claude Code bez nadzoru na laptopie z kluczami SSH i produkcyjnymi poświadczeniami do chmury. Jeden dev container rozwiązuje oba problemy, ale tylko wtedy, gdy jest zbudowany poprawnie: wiele gotowych konfiguracji instaluje Claude Code na nieobsługiwanej wersji Node’a, montuje do kontenera poświadczenia z hosta i powierza izolację sieci samej zmiennej proxy.
Ta strona jest dla programisty, który stawia kontener, i dla tech leada, który odpowiada za niego w zespole. Opisuje uruchamianie Claude Code wewnątrz kontenera. Pisanie Dockerfile’i i manifestów Kubernetes za pomocą Claude Code opisuje strona Docker i Kubernetes z Claude Code, a porównanie trybów uprawnień i sandboksów we wszystkich narzędziach — uprawnienia, sandboksy i tryby zatwierdzania.
Co daje zespołowy dev container dla Claude Code
Dział zatytułowany „Co daje zespołowy dev container dla Claude Code”devcontainer.json, który instaluje Claude Code oficjalnym feature’em i przeżywa przebudowę bez ponownego logowania.- Wariant z Dockerfile’em i przypiętą wersją, z polityką organizacji w
/etc/claude-code/managed-settings.json. - Firewall ruchu wychodzącego typu „domyślnie odrzucaj” i jasny obraz luk w referencyjnym skrypcie Anthropic.
- Zasady, kiedy
--dangerously-skip-permissionsjest dopuszczalne, a kiedy lepszym wyborem jest tryb auto albo sandbox Basha. - Job w CI, który przy każdej zmianie dowodzi, że kontener jest poprawny, więc nikt nie czyta
devcontainer.jsonlinijka po linijce. - Trzy prompty do skopiowania: szkielet, audyt i weryfikacja.
Jakiej izolacji potrzebujesz: dev containera, sandboksa Basha czy obu?
Dział zatytułowany „Jakiej izolacji potrzebujesz: dev containera, sandboksa Basha czy obu?”Claude Code ma dwie warstwy izolacji, które łatwo pomylić. Sandbox Basha jest wbudowany w Claude Code i ogranicza każde polecenie powłoki mechanizmami systemu (Seatbelt na macOS, bubblewrap na Linuksie i WSL2). Dev container odcina od hosta cały toolchain, łącznie z samym Claude Code.
| Sytuacja | Użyj | Dlaczego |
|---|---|---|
| Jedna osoba, zaufane repozytorium, sesje interaktywne | Sandbox Basha (/sandbox) na hoście | Bez narzutu Dockera; znika większość pytań o polecenia powłoki |
| Zespół, który potrzebuje identycznych narzędzi i szybszego onboardingu | Dev container z feature’em Claude Code | Jeden plik definiuje środowisko; polecenia działają w kontenerze, nie na laptopie |
| Przebiegi bez nadzoru z mniejszą liczbą pytań o zgodę albo bez nich | Dev container + firewall wychodzący + użytkownik bez roota | Ogranicza to, do czego sięgnie i co zmieni sesja z pominiętymi uprawnieniami |
| Pełny stos (baza, usługi, dane testowe) na każde zadanie agenta | Efemeryczne środowiska | Dev container to jedno długowieczne środowisko na programistę, a nie jedno na zadanie |
| Hostowane, jednorazowe sandboksy (E2B, Daytona, container-use) | Porównanie sandboksów dla agentów | Katalog narzędzi, poza zakresem tej strony |
Warstwy da się łączyć. Wewnątrz dev containera sandbox Basha nadal dokłada granicę na poziomie pojedynczego polecenia, ale ma to swój koszt, opisany w sekcji o awariach.
Dodaj Claude Code do devcontainer.json oficjalnym feature’em
Dział zatytułowany „Dodaj Claude Code do devcontainer.json oficjalnym feature’em”Anthropic publikuje Claude Code Dev Container Feature. Instaluje on CLI, doinstalowuje Node.js, gdy obraz bazowy go nie ma, i dodaje rozszerzenie Claude Code do VS Code, gdy otwierasz kontener w VS Code lub Codespaces. Używaj go zamiast npm install -g w postStartCommand, który instaluje wszystko od nowa przy każdym starcie. Zacznij od obrazu, który ma już Node 22 lub nowszy, bo tego wymaga pakiet npm (engines: node >=22.0.0 dla @anthropic-ai/claude-code 2.1.283, sprawdzone 2026-09-26). Na starszym Node npm wypisuje tylko ostrzeżenie EBADENGINE i instaluje CLI, którego twoje środowisko nie obsługuje. Awaryjna instalacja w samym feature’ze nie jest bezpieczniejsza: na obrazie Debiana/Ubuntu lub dystrybucji z yum bez Node’a jego install.sh dodaje repozytorium NodeSource 18.x, a inne dystrybucje dostają taki nodejs, jaki ma ich menedżer pakietów (sprawdzone na gałęzi main, wersja feature’a 1.0.5, 2026-09-26).
-
Zapisz poniższy plik jako
.devcontainer/devcontainer.jsonw katalogu głównym repozytorium albo dołącz blokifeatures,mountsicontainerEnvdo istniejącego pliku:{"name": "app + Claude Code","image": "mcr.microsoft.com/devcontainers/typescript-node:22","features": {"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}},"remoteUser": "node","mounts": ["source=claude-code-config-${devcontainerId},target=/home/node/.claude,type=volume"],"containerEnv": {"CLAUDE_CONFIG_DIR": "/home/node/.claude"},"postCreateCommand": "npm ci","forwardPorts": [3000]}Tag
:1.0śledzi skrypt instalacyjny feature’a z linii 1.0.x (do dokładnego przypięcia użyj:1.0.5), a nie wydanie Claude Code. Feature instaluje najnowsze Claude Code, które potem samo się aktualizuje w kontenerze. -
Przebuduj kontener. W VS Code lub Cursorze otwórz paletę poleceń i uruchom Dev Containers: Rebuild Container. Z terminala użyj Dev Containers CLI:
npx @devcontainers/cli up --workspace-folder . -
Otwórz terminal w kontenerze i uruchom
claude. Z kontem Anthropic zaloguj się przez przeglądarkę. Z Amazon Bedrock, Google Cloud lub Microsoft Foundry przekaż poświadczenia chmury jako zmienne środowiskowe (containerEnv, sekret Codespaces albo workload identity), a nie jako zamontowane pliki. Konfigurację dostawców opisuje strona uwierzytelnianie w Claude Code. -
W tym samym terminalu sprawdź podstawy:
claude --versionwypisuje wersję,node --versionwypisujev22lub nowszą wersję, awhoamiwypisujenode, nieroot.
Dlaczego nazwany wolumen, a nie bind mount ~/.claude?
Dział zatytułowany „Dlaczego nazwany wolumen, a nie bind mount ~/.claude?”Wiele przykładów montuje do kontenera katalog ~/.claude z hosta. Nie rób tego. Ten katalog trzyma twoje poświadczenia i historię sesji ze wszystkich projektów, a sesja z pominiętymi uprawnieniami może odczytać i wynieść wszystko, co jest w kontenerze. Z tego samego powodu przewodnik Anthropic po dev containerach ostrzega przed montowaniem sekretów hosta, takich jak ~/.ssh czy pliki poświadczeń chmury.
Nazwany wolumen z kroku 1 zachowuje logowanie i ustawienia użytkownika między przebudowami, nie dotykając hosta. CLAUDE_CONFIG_DIR jest potrzebne, bo Claude Code trzyma konto OAuth, osobiste serwery MCP i zaufanie do projektów w ~/.claude.json, czyli w pliku poza ~/.claude. Bez tej zmiennej wolumen przetrwa, ale po każdej przebudowie będziesz wylogowany. Przyrostek ${devcontainerId} daje każdemu repozytorium osobny wolumen, więc stan jednego projektu nigdy nie przecieka do drugiego.
Przypnij wersję Claude Code i wymuś politykę zespołu
Dział zatytułowany „Przypnij wersję Claude Code i wymuś politykę zespołu”Feature zawsze instaluje najnowsze wydanie. Gdy tech lead potrzebuje powtarzalnych buildów albo polityki, której projektowy .claude/settings.json nie nadpisze, przejdź na Dockerfile.
# .devcontainer/DockerfileFROM mcr.microsoft.com/devcontainers/typescript-node:22
# Przypnij CLI. 2.1.274 było dist-tagiem npm "stable" 2026-09-26.RUN npm install -g @anthropic-ai/claude-code@2.1.274
# Polityka organizacji: najwyższy priorytet w hierarchii ustawień na Linuksie.RUN mkdir -p /etc/claude-codeCOPY managed-settings.json /etc/claude-code/managed-settings.jsonPlik polityki leży obok jako .devcontainer/managed-settings.json:
{ "permissions": { "deny": ["Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)"] }}W devcontainer.json wskaż Dockerfile przez "build": { "dockerfile": "Dockerfile" } zamiast image i features, dodaj "customizations": { "vscode": { "extensions": ["anthropic.claude-code"] } }, żeby zachować rozszerzenie VS Code, które wcześniej dodawał feature, a do containerEnv dodaj "DISABLE_AUTOUPDATER": "1", żeby przypięcie się utrzymało. W środowiskach z ograniczoną telemetrią "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1" wyłącza też ruch niekonieczny. Wyłącza przy tym ewaluację feature flag, od której zależy Remote Control, więc Remote Control nie działa w kontenerze. Jeśli go potrzebujesz, ustaw tylko DISABLE_TELEMETRY (v2.1.283+); wtedy Remote Control pozostaje dostępny, chyba że organizacja wymaga Trusted Devices.
Udostępnij konfigurację projektu i serwery MCP przez repozytorium
Dział zatytułowany „Udostępnij konfigurację projektu i serwery MCP przez repozytorium”Wszystko, co ma zasięg projektu, przychodzi razem z checkoutem: CLAUDE.md, .claude/settings.json, .claude/skills/, .claude/agents/ i .mcp.json. Zespołowe serwery MCP definiuj w zasięgu projektu w .mcp.json (zobacz konfigurację serwerów MCP w Claude Code), a potem zrób dwie rzeczy, których checkout za ciebie nie zrobi:
- Zainstaluj w Dockerfile’u binaria potrzebne serwerom stdio (
uv, klient bazy danych), żeby pierwsze wywołanie MCP nie padło na brakującym pliku wykonywalnym. - Dodaj domenę każdego zdalnego serwera MCP do listy dozwolonych w firewallu opisanym niżej.
Użyj tego samego kontenera w GitHub Codespaces
Dział zatytułowany „Użyj tego samego kontenera w GitHub Codespaces”Codespaces uruchamia ten sam devcontainer.json w chmurze. Dwie rzeczy różnią się od kontenera lokalnego:
~/.claudeprzetrwa zatrzymanie i wznowienie codespace’a, ale znika przy przebudowie, więc zostaw konfigurację z wolumenem iCLAUDE_CONFIG_DIR.- Żeby pozostać zalogowanym między codespace’ami, zapisz
ANTHROPIC_API_KEYalboCLAUDE_CODE_OAUTH_TOKENwygenerowany przezclaude setup-token(wymaga subskrypcji Claude) jako sekret użytkownika Codespaces. Codespaces udostępnia sekrety w kontenerze jako zmienne środowiskowe.
Zadeklaruj sekret w devcontainer.json, żeby Codespaces poprosił o niego przy tworzeniu codespace’a:
{ "secrets": { "CLAUDE_CODE_OAUTH_TOKEN": { "description": "Long-lived Claude Code token from `claude setup-token`" } }}Nigdy nie wpisuj klucza na sztywno do devcontainer.json ani nie przekazuj go przez ${localEnv:...} do pliku, który commitujesz.
Ogranicz ruch wychodzący firewallem „domyślnie odrzucaj”
Dział zatytułowany „Ogranicz ruch wychodzący firewallem „domyślnie odrzucaj””Własna sieć Dockera plus HTTPS_PROXY niczego nie izoluje: nic nie zmusza ruchu do przejścia przez proxy, a bezpośrednie połączenie nadal wychodzi z kontenera. Zmiennej proxy używaj do routingu (zobacz konfigurację proxy dla Claude Code), a firewalla do izolacji.
Referencyjny dev container Anthropic zawiera init-firewall.sh, który ustawia domyślną politykę iptables na DROP, przepuszcza opublikowane zakresy IP GitHuba i krótką listę rozwiązanych domen, a na koniec sam się sprawdza: kończy się błędem, jeśli https://example.com jest osiągalne albo https://api.github.com nie jest. Skrypt potrzebuje narzędzi, których obraz z kroku 1 nie ma. Skopiuj init-firewall.sh z wersji referencyjnej do .devcontainer/; to wymaga wariantu z Dockerfile’em, a nie pliku z obrazem i feature’em z kroku 1. Dopisz do Dockerfile’a:
RUN apt-get update && apt-get install -y --no-install-recommends \ iptables ipset dnsutils aggregate jq curl \ && rm -rf /var/lib/apt/lists/*COPY init-firewall.sh /usr/local/bin/init-firewall.shRUN chmod +x /usr/local/bin/init-firewall.shPotem podłącz go tak jak w wersji referencyjnej:
{ "runArgs": ["--cap-add=NET_ADMIN", "--cap-add=NET_RAW"], "postStartCommand": "sudo /usr/local/bin/init-firewall.sh", "waitFor": "postStartCommand"}Nie przejmuj skryptu bez zmian. Jego luki, sprawdzone na gałęzi main 2026-09-26:
- Rozwiązuje domeny na adresy IP raz, przy starcie. Rejestr albo CDN, które rotują adresy, przestają działać w trakcie sesji.
postStartCommanduruchamia skrypt przy każdym starcie kontenera, więc restart kontenera jest sposobem naprawy. - Jego lista domen nie pokrywa wszystkiego, czego potrzebuje Claude Code. Przepuszcza
api.anthropic.com, ale nieclaude.aianiplatform.claude.com, których według wymagań sieciowych Anthropic używają logowanie przez przeglądarkę i odświeżanie tokenów OAuth. Dopiszclaude.aiiplatform.claude.comdo listyfor domain in(orazmcp-proxy.anthropic.com, jeśli używasz connectorów claude.ai) albo uwierzytelniaj się przezCLAUDE_CODE_OAUTH_TOKEN/ANTHROPIC_API_KEY. - Przepuszcza całą sieć /24 hosta. Każda usługa w tej sieci, w tym inne kontenery, pozostaje osiągalna.
- Referencyjny Dockerfile startuje z
node:20, czyli poniżej minimum Node 22 wymaganego przez obecny pakiet npm. Zmień obraz bazowy, kiedy go kopiujesz.
Dopisz do listy for domain in własne rejestry pakietów, hosta VCS, jeśli to nie GitHub, oraz domeny zdalnych serwerów MCP.
Uruchamiaj Claude Code bez nadzoru wewnątrz kontenera
Dział zatytułowany „Uruchamiaj Claude Code bez nadzoru wewnątrz kontenera”Kontener uruchamia Claude Code jako użytkownika bez roota i zamyka polecenia w kontenerze. To sprawia, że claude --dangerously-skip-permissions jest rozsądne wyłącznie w kontenerze z opisanym wyżej firewallem i na zaufanym repozytorium. CLI odrzuca tę flagę, gdy działa jako root. Sesja z pominiętymi uprawnieniami nadal może zmienić każdy plik w zamontowanym workspace, a te zmiany natychmiast pojawiają się na hoście.
Najpierw sięgnij po węższą opcję:
- Tryb auto zostawia klasyfikator, który ocenia każdą akcję. Od v2.1.283 (oba kanały wydań na 2026-10-12) jest trybem startowym interaktywnych sesji w terminalu i VS Code na obsługiwanych modelach.
claude -pnadal startuje w trybie Manual (od v2.1.285 w trybie auto u zewnętrznych dostawców lub z wyłączoną telemetrią). Przypięty wyżej obraz 2.1.274 jest starszy niż v2.1.283, więc jego sesje nadal startują w trybie Manual, dopóki nie przesuniesz przypięcia na 2.1.283 lub nowszą (2026-10-12stableto 2.1.287). W przebiegach headless przekaż--permission-mode autoalbo przypnij dokładną listę dozwolonych narzędzi:claude -p "run the test suite" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read". - Sandbox Basha usuwa większość pytań o polecenia powłoki, zachowując granicę dla każdego polecenia. Włącz go przez
/sandboxalbo ustaw"sandbox": { "enabled": true }w.claude/settings.json. - Żeby zabronić trybu bypass całemu zespołowi, ustaw
permissions.disableBypassPermissionsModena"disable"w ustawieniach zarządzanych.
Pełne porównanie trybów w Claude Code, Codex i Cursorze znajdziesz na stronie uprawnienia, sandboksy i tryby zatwierdzania.
Jak udowodnić, że dev container działa, bez czytania go?
Dział zatytułowany „Jak udowodnić, że dev container działa, bez czytania go?”Recenzent nie wyczyta z diffu devcontainer.json, czy logowanie nadal przetrwa przebudowę i czy firewall nadal blokuje ruch. Job w CI to sprawdzi. Akcja devcontainers/ci buduje kontener z twojej prawdziwej konfiguracji i uruchamia w nim polecenie. Poniższy job nie potrzebuje żadnych sekretów, bo żadne ze sprawdzeń nie woła modelu:
name: devcontaineron: pull_request: paths: ['.devcontainer/**', '.mcp.json', '.claude/**']permissions: contents: readjobs: smoke: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 with: persist-credentials: false - uses: devcontainers/ci@v0.3 with: push: never runCmd: bash .devcontainer/smoke-test.sh#!/usr/bin/env bash# .devcontainer/smoke-test.sh: każda linia zatrzymuje job przy regresjiset -euo pipefailtest "$(whoami)" != "root" # --dangerously-skip-permissions wymaga użytkownika bez rootanode -e 'process.exit(+process.versions.node.split(".")[0] >= 22 ? 0 : 1)' # Node 22+claude --version | grep -q '^2\.1\.274 ' # przypięcie z Dockerfile'a działatest "$CLAUDE_CONFIG_DIR" = "$HOME/.claude" # logowanie przetrwa przebudowętest -f /etc/claude-code/managed-settings.json # polityka zespołu jest w obrazieif curl -s --max-time 5 https://example.com >/dev/null; then echo "egress not blocked"; exit 1ficurl -s --max-time 5 -o /dev/null https://api.anthropic.com # API modelu jest osiągalnenpm test # testy projektu przechodzą w kontenerzeUsuń linie z wersją i managed-settings.json, jeśli używasz feature’a zamiast Dockerfile’a, a sprawdzenie ruchu wychodzącego, jeśli nie uruchamiasz firewalla. Dodaj .devcontainer/ do CODEOWNERS, żeby zmiany zatwierdzał tech lead. Przy zielonym jobie dymnym to zatwierdzenie sprawdza intencję, a nie każdą linijkę.
Użyj tego samego kontenera z Cursorem i Codexem
Dział zatytułowany „Użyj tego samego kontenera z Cursorem i Codexem”Kontener nie jest związany z Claude Code. Cursor obsługuje specyfikację Dev Containers, więc otwiera ten sam devcontainer.json, a CLI Claude Code działa w jego zintegrowanym terminalu. Dla Codex dodaj npm install -g @openai/codex do Dockerfile’a i dopisz hosty Codex do firewalla: api.openai.com przy logowaniu kluczem API oraz chatgpt.com i auth.openai.com przy logowaniu kontem ChatGPT (domyślne endpointy w binarce Codex 0.157.1, sprawdzone 2026-09-26). Hostowane środowiska Codex to osobny system, opisany na stronie środowiska chmurowe Codex.
Co się psuje w dev containerze z Claude Code?
Dział zatytułowany „Co się psuje w dev containerze z Claude Code?”Build zatrzymuje się na Failed to install Node.js and npm albo claude pada przy starcie. Obraz bazowy nie ma Node’a, a feature albo nie zdołał go zainstalować, albo zainstalował Node 18. Dodaj "ghcr.io/devcontainers/features/node:1": { "version": "22" } w features przed feature’em Claude Code, przebuduj kontener i sprawdź, czy node --version wypisuje v22 lub nowszą wersję.
npm install -g @anthropic-ai/claude-code wypisuje EBADENGINE. Node w obrazie jest starszy niż 22. Przejdź na obraz z Node 22 lub nowszym; feature tu nie pomoże, bo zostawia Node’a, którego obraz już ma.
Logowanie w przeglądarce się kończy, ale terminal go nie dostaje. Przekierowanie portów w edytorze nie przepuściło callbacku na localhost. Skopiuj kod z przeglądarki i wklej go w terminalu przy Paste code here if prompted.
Po każdej przebudowie jesteś wylogowany. Wolumen jest zamontowany, ale brakuje CLAUDE_CONFIG_DIR, więc ~/.claude.json ląduje w katalogu domowym, który przebudowa wyrzuca. Ustaw zmienną na ścieżkę docelową wolumenu.
EACCES na ~/.claude po pierwszym starcie. Wolumen utworzył inny użytkownik. Uruchom raz sudo chown -R node:node /home/node/.claude albo usuń wolumen przez docker volume rm i przebuduj.
--dangerously-skip-permissions jest odrzucane. Claude Code działa jako root. Ustaw remoteUser na użytkownika obrazu bez roota i przebuduj.
Polecenia w sandboksie padają z Can't mount proc on /newroot/proc: Operation not permitted. Bubblewrap nie może zamontować świeżego /proc w nieuprzywilejowanym kontenerze. Ustaw sandbox.enableWeakerNestedSandbox na true tylko wtedy, gdy granicą, na której polegasz, są firewall i izolacja użytkownika samego kontenera; to ustawienie wyraźnie osłabia wewnętrzny sandbox.
npm install, zdalny serwer MCP albo logowanie kończą się timeoutem po starcie firewalla. Cel nie jest na liście dozwolonych albo zmienił adres IP po tym, jak skrypt go rozwiązał. Dopisz domenę do init-firewall.sh i zrestartuj kontener.
claude --resume nie pokazuje sesji z hosta. Sesje są zapisywane per ścieżka projektu, a ścieżka w kontenerze (/workspaces/app) różni się od ścieżki na hoście. To oczekiwane zachowanie. Zaczynaj nowe sesje w kontenerze.
Dokąd dalej z Claude Code w zespole
Dział zatytułowany „Dokąd dalej z Claude Code w zespole”- Claude Code w zespole i firmie — przegląd sekcji i kolejność wdrażania.
- Integracja korporacyjna Claude Code — ustawienia zarządzane, których inżynierowie nie wyedytują.
- Konfiguracja proxy dla Claude Code — ruch z kontenera przez firmowe proxy.
- Współpraca zespołowa z Claude Code — wspólny
CLAUDE.md, skille i zasady review, które kontener przenosi. - Claude Code w CI/CD — przebiegi headless, które często używają tego samego obrazu.