Claude Code in a dev container: setup, firewall and auth

Claude Code in a devcontainer is one feature line. A named volume and one env variable keep your sign-in through rebuilds; skipping prompts stays unsafe.

Contents

Add one line to .devcontainer/devcontainer.json, Anthropic's feature ghcr.io/anthropics/devcontainer-features/claude-code:1.0, rebuild, and Claude Code is installed in the dev container; run claude in its terminal. Commands Claude runs then execute inside the container, and the files it edits are your repository on the host.

Every setting below comes from Anthropic's dev container page, read on 23 October 2026, and from its reference container on GitHub.

How to set up Claude Code in a devcontainer#

  1. Save this as .devcontainer/devcontainer.json, or add the features block to the file you have:

    json
    {
      "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
      "features": {
        "ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
      }
    }
    

    Swap the image line for your project's base image, or drop it if your file builds from a Dockerfile.

  2. Rebuild. In VS Code that's Cmd+Shift+P (Mac) or Ctrl+Shift+P, then Dev Containers: Rebuild Container. Codespaces, JetBrains IDEs, Cursor and the Dev Containers CLI each have their own rebuild action.

  3. Open a terminal in the container and run claude. Sign in with your Claude or Console account in the browser. If the browser finishes but the terminal never hears back (port forwarding didn't route the callback), copy the code from the browser and paste it at Paste code here if prompted.

In VS Code and Codespaces the feature also adds the Claude Code extension. Both the extension and the terminal claude run inside the container and share one ~/.claude. What stays behind on your laptop when VS Code opens a container, a WSL distro or an SSH host is in Claude Code with VS Code Remote-SSH, WSL and containers.

An image without Node.js gets it from the Claude Code feature. When that install breaks, the build stops with Failed to install Node.js and npm, and the fix is one more line in features, above Claude Code's: "ghcr.io/devcontainers/features/node:1": {}.

Why you sign in again after every rebuild#

A rebuild throws away the container's home directory, and with it everything Claude Code keeps there: the sign-in, your settings and session history in ~/.claude, and the account details, personal MCP servers and per-project trust in ~/.claude.json, which sits outside that folder.

The fix is a named volume on ~/.claude plus CLAUDE_CONFIG_DIR pointing at it, which moves .claude.json into the volume as well. In devcontainer.json:

json
"mounts": [
  "source=claude-code-config,target=/home/node/.claude,type=volume"
],
"containerEnv": {
  "CLAUDE_CONFIG_DIR": "/home/node/.claude"
}

Replace /home/node with your remoteUser's home. Forget the CLAUDE_CONFIG_DIR line and Claude Code runs its first-launch setup again on every rebuild, because the record that you finished it lived in the discarded .claude.json. For one volume per project instead of one shared by every repository, put ${devcontainerId} in the source name, as Anthropic's reference file does (claude-code-config-${devcontainerId}).

Codespaces keeps ~/.claude when you stop and start a codespace and clears it on rebuild, so the same fix applies. To carry a sign-in across codespaces, store ANTHROPIC_API_KEY, or a CLAUDE_CODE_OAUTH_TOKEN from claude setup-token, as a Codespaces secret. The whole codespace setup, sign-in included, is in Claude Code in GitHub Codespaces.

CLAUDE_CONFIG_DIR is the same switch people use for two Claude Code profiles on one machine; our CLAUDE_CONFIG_DIR guide covers that side of it.

Pin the version, set team policy#

The :1.0 at the end of the feature pins the install script, not Claude Code. The feature always installs the latest release, and Claude Code updates itself in the container by default. For builds that come out the same every time:

  • install a fixed version in the Dockerfile with npm install -g @anthropic-ai/claude-code@X.Y.Z instead of the feature;
  • set "DISABLE_AUTOUPDATER": "1" in containerEnv.

On Linux, Claude Code reads /etc/claude-code/managed-settings.json at the highest precedence, so a Dockerfile can copy a team policy into place:

dockerfile
RUN mkdir -p /etc/claude-code
COPY managed-settings.json /etc/claude-code/managed-settings.json

Anthropic points out the catch: the Dockerfile lives in the repository, so anyone who can write to it can remove that step. Policy people must not be able to edit away goes through server-managed settings or MDM instead.

MCP servers the whole team needs belong in a project-scope .mcp.json at the repository root. Install whatever binaries their stdio commands need in the Dockerfile, and add remote servers' domains to the firewall's list.

The firewall in the reference container#

Anthropic keeps a fuller example in the anthropics/claude-code repository. Three files:

File What it does
devcontainer.json Volume mounts, runArgs capabilities, VS Code extensions, containerEnv
Dockerfile Base image, development tools, the Claude Code install
init-firewall.sh Limits outbound traffic to the destinations the script allows

init-firewall.sh runs as the postStartCommand. It sets the OUTPUT policy to DROP, then allows GitHub's ranges from api.github.com/meta, your host's /24, and seven domains: registry.npmjs.org, api.anthropic.com, sentry.io, statsig.com and three VS Code hosts. Everything else is rejected, and the script checks itself by trying https://example.com, which must fail. Anything else your project fetches, a PyPI mirror or a remote MCP server, goes into its for domain in list.

Running a firewall inside a container needs extra rights, so the reference adds the NET_ADMIN and NET_RAW capabilities. Claude Code itself needs neither the script nor the capabilities; you can rely on your own network controls instead. Anthropic calls the reference "a working example rather than a maintained base image". Copy its .devcontainer/ folder into your repository and adjust the Dockerfile for your toolchain, rather than building on it as a dependency.

Is --dangerously-skip-permissions safe in a dev container?#

It is safer than on your laptop and still not safe. Claude Code runs as a non-root user in the container and its commands stay inside, which is why Anthropic allows skipping prompts there for unattended runs. The CLI refuses the flag as root, so check remoteUser (the reference uses node).

What the container does not stop, in Anthropic's words: "When executed with --dangerously-skip-permissions, dev containers do not prevent a malicious project from exfiltrating anything accessible inside the container, including the Claude Code credentials stored in ~/.claude." And Claude can still change any file in the bind-mounted workspace, which is your real repository on the host.

Four conditions before a run with prompts off:

  1. Trusted repositories only.
  2. Outbound traffic limited to what the session needs (the firewall above, or your own rules).
  3. No ~/.ssh or cloud credential files in mounts; short-lived or repository-scoped tokens instead.
  4. A commit before the run, so git diff shows what changed and git can take you back.

Anthropic's alternative for fewer prompts, not none, is auto mode: a classifier reviews each action before it runs. Teams that want bypass mode gone set permissions.disableBypassPermissionsMode to "disable" in managed settings. Our guide to skipping permissions safely compares the options outside a container, and keeping secrets away from coding agents covers the .env side.

When a server suits better than a container#

A dev container isolates one project on your own computer. If what you are after is agents that run away from your laptop altogether, overnight or with the lid shut, a machine of your own does that job. Shuriken can run your agents on a server you own: add it under Settings › Devices › Add device › A server, and its chats show on every device you use. The prompt-injection guide applies wherever the agent runs.

Sources

  1. Development containers (Claude Code docs) (accessed 23 October 2026)
  2. Reference dev container: devcontainer.json, Dockerfile, init-firewall.sh (anthropics/claude-code on GitHub) (accessed 25 October 2026)
  3. Claude Code Dev Container Feature (anthropics/devcontainer-features on GitHub) (accessed 23 October 2026)

Frequently asked questions

How do I add Claude Code to a dev container?

Add the feature ghcr.io/anthropics/devcontainer-features/claude-code:1.0 to the features block of .devcontainer/devcontainer.json, rebuild the container, then run claude in its terminal and sign in.

Why do I have to sign in to Claude Code again after every rebuild?

The container's home directory is thrown away on rebuild. Mount a named volume at ~/.claude and set CLAUDE_CONFIG_DIR to the same path, so both the folder and .claude.json survive.

Is --dangerously-skip-permissions safe inside a dev container?

Safer than on your laptop, not safe. Anthropic's docs say a malicious project can still take anything inside the container, including the Claude Code credentials, so use it only with repositories you trust and with the network locked down.

Does the dev container feature pin the Claude Code version?

No. The :1.0 is the install script's version. The feature installs whichever Claude Code release is newest at build time, and that copy updates itself; for a fixed version, run npm install -g @anthropic-ai/claude-code@X.Y.Z in your Dockerfile and set DISABLE_AUTOUPDATER=1.

Free tools