Who this is for and what you will be able to do
This guide is for developers who want every engineer on a team to run Claude Code in the same isolated environment, and for the people who set the team's rules. After reading it, you can add a dev container to a repository, make Claude Code's commands run inside the container, keep sign-in across rebuilds, and understand which settings raise the risk.
What a dev container is
A dev container, or development container, is an isolated environment defined by configuration, so every engineer on the team can run the same one[1]. With Claude Code installed in it, the commands Claude runs execute inside the container, while the edits to your project files appear in your local repository as you work[1].
A dev container runs as a Docker container, on your own machine or on a cloud host such as GitHub Codespaces[1]. Editors that support the Dev Containers spec, such as VS Code, GitHub Codespaces, a JetBrains IDE or Cursor, connect to it. The integrated terminal, language servers and build tools all run inside the container. Editors without dev container support, such as plain Vim, do not fit this workflow[1].
In VS Code you can use the Claude Code extension panel or run claude in the integrated terminal. Both run inside the container and share the same ~/.claude configuration[1].
Step 1: Add the feature to devcontainer.json
Save the following as .devcontainer/devcontainer.json in your repository, or add the features block to your existing file[1]:
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
}
}The :1.0 tag pins the feature's install script, not the Claude Code release. The feature installs the latest Claude Code, and Claude Code updates itself inside the container by default[1]. To pin the version or turn off auto-update, see the organization policy section below.
Replace the image line with your project's base image, or delete it if your file uses a Dockerfile[1]. The feature installs Node.js itself when the base image does not have it. If the build stops with Failed to install Node.js and npm, add "ghcr.io/devcontainers/features/node:1": {} to the features block above the Claude Code feature, then rebuild[1].
Step 2: Rebuild the container
In VS Code, press Cmd+Shift+P on Mac or Ctrl+Shift+P on Windows and Linux, and run Dev Containers: Rebuild Container[1]. In GitHub Codespaces and other tools, use that tool's own rebuild action[1].
Step 3: Sign in
Open a terminal in the rebuilt container, run claude, and follow the authentication prompt[1].
- Anthropic account: sign in through a browser with a Claude or Anthropic Console account[1].
- Cloud provider: with Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry, Claude Code uses your cloud provider credentials and shows no browser prompt[1].
For a cloud provider, pass the credentials in as environment variables, through containerEnv, a Codespaces secret or your cloud's workload identity. Do not mount credential files from the host[1].
Keep sign-in and settings across rebuilds
By default the container's home directory is discarded on rebuild, so engineers have to sign in again each time[1]. Claude Code keeps its authentication token, user settings and session history under ~/.claude. Account details, personal MCP servers and per-project trust live in ~/.claude.json, outside that directory[1].
To keep both, mount a named volume at ~/.claude and set CLAUDE_CONFIG_DIR to the same path, so .claude.json is written into the volume too[1]:
"mounts": [
"source=claude-code-config,target=/home/node/.claude,type=volume"
],
"containerEnv": {
"CLAUDE_CONFIG_DIR": "/home/node/.claude"
}This example assumes the container's remoteUser is node. Replace /home/node with the home directory of your remoteUser. If containerEnv already exists, add CLAUDE_CONFIG_DIR to that object rather than writing a second one[1].
If the volume is mounted but first-launch setup still repeats after each rebuild, check that CLAUDE_CONFIG_DIR is set. Without it, ~/.claude.json stays in the home directory and is discarded on rebuild, together with the record that setup was completed[1].
To keep state separate for each project instead of sharing one volume, include ${devcontainerId} in the volume source name. The reference configuration does this with source=claude-code-config-${devcontainerId}[1].
In GitHub Codespaces, ~/.claude survives stopping and starting a codespace, but a container rebuild clears it[1]. To carry sign-in across codespaces, store ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN as a Codespaces secret. The secret is exposed to the container as an environment variable automatically[1]. The token comes from claude setup-token[1].
Use organization policy
The same image and configuration run on every engineer's machine, so the dev container is a good place to apply organization policy. On Linux, Claude Code reads /etc/claude-code/managed-settings.json and gives it the highest precedence in the settings hierarchy. Its values override anything set in ~/.claude or the project's .claude/ directory[1]. Copy the file into place from your Dockerfile[1]:
RUN mkdir -p /etc/claude-code
COPY managed-settings.json /etc/claude-code/managed-settings.jsonThe Dockerfile sits in the repository, so anyone with write access can change or remove this step. Policy that engineers must not be able to bypass should come from server-managed settings or MDM instead[1].
To set environment variables for every session in the container, add them to containerEnv. The example below opts out of telemetry and error reporting, and stops Claude Code from updating itself after install[1]:
"containerEnv": {
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1",
"DISABLE_AUTOUPDATER": "1"
}Be aware that CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC also turns off the feature-flag fetching that Remote Control depends on, so sessions in the container cannot use Remote Control[1].
To pin one Claude Code version for reproducible builds, skip the feature and install it in the Dockerfile with npm install -g @anthropic-ai/claude-code@X.Y.Z. Set DISABLE_AUTOUPDATER to 1 in containerEnv[1].
Limit network access
You can restrict the container's outbound traffic to the domains Claude Code needs. The network access requirements list the inference and authentication domains, and the telemetry page explains how to disable the optional connections[1].
The reference container includes an init-firewall.sh script that limits outbound traffic. Running a firewall inside a container needs the NET_ADMIN and NET_RAW capabilities, which the reference adds through runArgs. Claude Code itself does not need the script or those capabilities. You can leave them out and rely on your own network controls[1].
Skipping prompts: what the risk is
The container runs Claude Code as a non-root user and keeps command execution inside the container. That is why you can pass --dangerously-skip-permissions for unattended runs. The CLI rejects the flag when it runs as root, so confirm that remoteUser is a non-root account[1].
The flag removes your chance to review each tool call before it runs. Claude can still change any file in the bind-mounted workspace, and those files appear directly on your host. It can also reach anything the container's network policy allows. Pair the flag with the network restrictions above[1].
Even inside a container, no system is completely immune to attack. With this flag, a malicious project can send out anything the container can read, including the Claude Code credentials stored in ~/.claude[1]. Use dev containers only with trusted repositories, watch what Claude does, and keep host secrets such as ~/.ssh or cloud credential files out of the container. Prefer tokens that are scoped to one repository or short-lived[1].
For fewer prompts without giving up safety checks, use auto mode, in which a classifier reviews actions before they run[1]. To stop engineers from using the flag at all, set permissions.disableBypassPermissionsMode to "disable" in managed settings[1].
Try the reference container
The anthropics/claude-code repository has an example dev container. It combines the CLI, the egress firewall, persistent volumes and a Zsh-based shell. It is a working example, not a maintained base image, so use it to see how the pieces fit before you adapt them[1]. It has three files: devcontainer.json for mounts, runArgs capabilities, VS Code extensions and containerEnv; a Dockerfile for the base image, tools and the Claude Code install; and init-firewall.sh for outbound traffic[1].
Where to go next
For a rollout across an organization, read the organization setup guide first, then server-managed settings and usage monitoring. To see what the .claude directory stores, read its reference page. To compare dev containers with the built-in Bash sandbox and other isolation options, read the sandbox environments page[1].
Sources
- 1Development containersAnthropic Claude Code docs
Cite this page: Running Claude Code safely in a dev container. TellWorld, https://www.tellworld.net/practice/practice-claude-code-devcontainer. Updated 2026-11-14