To run Claude Code in Docker, install it in an image with the native installer or npm install -g @anthropic-ai/claude-code, mount your project into the container, pass a credential such as ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN, and run claude as a non-root user. If you work in VS Code, Codespaces or a JetBrains IDE, the official Dev Container Feature does most of this for you.
The main reason to use a container is isolation: commands Claude runs execute inside it, not on your machine, which makes unattended runs much safer. This guide follows Anthropic's sandbox environments and development containers pages, read on 26 October 2026.
Why run Claude Code in a container?
Claude Code's own sandbox only wraps shell commands. Built-in file tools, MCP servers and hooks still run on your host. A container puts the whole Claude Code process inside one boundary.
Anthropic compares the options like this:
| Approach | What is isolated | Needs Docker | Setup effort |
|---|---|---|---|
Sandboxed Bash tool (/sandbox) |
Shell commands and their child processes | No | Minimal on macOS, low on Linux and WSL2 |
Sandbox runtime (srt claude) |
The whole Claude Code process | No | Low |
| Dev container | Full development environment | Yes | Medium |
| Custom container | Full development environment | Yes | Medium to high |
| Virtual machine | Full operating system | No | High |
| Cloud sessions | Full OS, hosted by Anthropic | No | None; needs a Claude subscription |
The docs are direct about unattended work: "Always run --dangerously-skip-permissions sessions inside a container, a VM, or the sandbox runtime." For an untrusted repository, they recommend a dedicated VM or a cloud session over a container.
How do you build a Docker image with Claude Code?
Claude Code runs on Ubuntu 20.04+, Debian 10+ and Alpine Linux 3.19+, with 4 GB of RAM or more, according to the setup page. The docs list npm, the native installer, and apt, dnf or apk packages; the two below are the simplest in a Dockerfile.
npm. The package needs Node.js 22 or later. The Dockerfile below is our own example, not an official Anthropic image; it uses only the documented npm install -g @anthropic-ai/claude-code command:
# Example only: not an official Anthropic image
FROM node:22-bookworm-slim
RUN apt-get update \
&& apt-get install -y --no-install-recommends git ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# install as the non-root "node" user that ships with this image
USER node
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH=$PATH:/home/node/.npm-global/bin
# pin a release with: docker build --build-arg CLAUDE_CODE_VERSION=X.Y.Z .
ARG CLAUDE_CODE_VERSION=latest
RUN npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION}
# create the config folder as "node" so a named volume mounted here is writable
RUN mkdir -p /home/node/.claude
# the image controls the version, so stop self-updates
ENV DISABLE_AUTOUPDATER=1
WORKDIR /workspace
The devcontainer docs recommend installing a pinned @anthropic-ai/claude-code@X.Y.Z and setting DISABLE_AUTOUPDATER for reproducible builds, so pass a release number with --build-arg instead of relying on latest. The docs also warn against sudo npm install -g, which is why the example installs into a user-owned prefix. Creating /home/node/.claude as the node user lets the non-root user write to a named volume mounted there later.
Native installer. Run curl -fsSL https://claude.ai/install.sh | bash as the user who will run Claude Code. It places the launcher at ~/.local/bin/claude. Add a version to pin it: bash -s 2.1.89 in the docs' example.
On Alpine, the docs say to install bash, curl, libgcc, libstdc++ and ripgrep first, then set USE_BUILTIN_RIPGREP to 0 in your settings env.
How do you run it and sign in?
Mount your project and pass a credential from your shell, never baked into the image:
docker build -t claude-code .
docker run -it --rm \
-v "$PWD":/workspace \
-e ANTHROPIC_API_KEY \
claude-code claude
-e ANTHROPIC_API_KEY with no value copies the variable from your shell. Pick the credential that matches how you pay:
| You have | Pass this | Notes |
|---|---|---|
| A Claude Console account | ANTHROPIC_API_KEY |
Billed per token |
| A Pro, Max, Team or Enterprise plan | CLAUDE_CODE_OAUTH_TOKEN |
Create it with claude setup-token on a machine with a browser; it lasts one year |
| Bedrock, Agent Platform or Foundry | CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX or CLAUDE_CODE_USE_FOUNDRY plus your cloud credentials |
No browser prompt |
| Nothing scripted | Run claude and sign in |
If the browser callback never reaches the container, paste the code at Paste code here if prompted |
According to the authentication docs, claude setup-token "does not save the token anywhere", so copy it into your secret store straight away. Our environment variables guide explains which credential wins when several are set.
How do you keep your login and settings between runs?
Claude Code keeps credentials, settings and history in ~/.claude, and account details and per-project trust in ~/.claude.json. On Linux, credentials live in ~/.claude/.credentials.json. A fresh container loses all of it.
The fix from the devcontainer docs works in plain Docker too: mount a named volume at ~/.claude and point CLAUDE_CONFIG_DIR at it, so .claude.json lands in the volume as well.
docker run -it --rm \
-v "$PWD":/workspace \
-v claude-config:/home/node/.claude \
-e CLAUDE_CONFIG_DIR=/home/node/.claude \
claude-code claude
Without CLAUDE_CONFIG_DIR, Claude Code repeats first-run setup each time because .claude.json stays outside the volume.
How do you run Claude Code unattended in Docker?
Combine headless mode with bypass permissions, as a non-root user:
docker run --rm \
-v "$PWD":/workspace \
-e CLAUDE_CODE_OAUTH_TOKEN \
claude-code \
claude -p "run the tests and fix any failures" --dangerously-skip-permissions
If the container runs as root, Claude Code stops with: --dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons. That is why the image above switches to the node user.
Keep in mind what the container does not stop. The docs warn that with this flag, a malicious project can exfiltrate anything inside the container, "including the Claude Code credentials stored in ~/.claude." Claude can also change every file in the mounted folder, and those changes land on your host. Use trusted repositories, avoid mounting ~/.ssh or cloud credential files, and prefer short-lived tokens.
For a middle ground, auto mode has a classifier review each action instead of skipping checks. See our headless guide for output formats and --max-turns, and our permissions guide for allow and deny rules.
How do you limit network access from the container?
Network egress is what turns a contained mistake into a data leak, so allow only what Claude Code needs. The network configuration page lists the hosts, including:
| Host | Needed for |
|---|---|
api.anthropic.com |
Claude API requests |
claude.ai |
claude.ai account sign-in |
platform.claude.com |
Console sign-in, and OAuth token refresh for claude.ai accounts |
downloads.claude.ai |
Native installer and auto-updates |
registry.npmjs.org |
npm installs and npx-launched MCP servers |
Anthropic's reference dev container ships an init-firewall.sh script with a default-deny allowlist. Running a firewall inside a container needs the NET_ADMIN and NET_RAW capabilities, but the docs note you can skip the script and rely on your own network controls instead.
Behind a corporate proxy, set HTTPS_PROXY and, for a custom CA, NODE_EXTRA_CA_CERTS.
Can you use /sandbox inside a container?
Yes. Layering the Bash sandbox inside a container adds per-command limits on top of the container boundary. In an unprivileged container, though, bubblewrap can't mount a fresh /proc and fails with an error like Can't mount proc on /newroot/proc: Operation not permitted. The sandboxing docs say to set sandbox.enableWeakerNestedSandbox to true in that case, and only when the outer container already gives you the isolation you need.
Should you use a devcontainer instead?
If your team opens projects in VS Code, GitHub Codespaces or a JetBrains IDE, probably yes. Add one line to .devcontainer/devcontainer.json:
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
}
}
The :1.0 tag pins the install script, not Claude Code, which installs at the latest version. Organizations can copy a managed-settings.json to /etc/claude-code/ in the Dockerfile for policy, though anyone with write access to the repo can change that step. Our devcontainer guide covers persistence, policy and the reference firewall in detail.
For the strongest separation, the docs point to a virtual machine, Docker Sandboxes (a microVM product from Docker) or Anthropic-hosted cloud sessions.
How do you bring your skills into the container?
A clean container starts without your personal skills. If you keep them in a GitHub repo, one command in your image or startup script can install them. Kipt, for example, stores prompts and Agent Skills as Markdown in a private repo you own and installs every skill into Claude Code with npx skills add https://github.com/<you>/<repo>.git --all -g. In practice, that step needs network access to GitHub and the npm registry, and because the repo is private, git inside the container also needs credentials that can read it. Pass a read-only token at run time rather than baking it into the image.