Skip to content
zero2vibecodelearn vibe coding
Level 6 · Electives 9 min Reviewed by the author · Oct 15, 2026 Verified against Claude Code v2.1.292 · Oct 15, 2026Official docs: Dev containersSomething out of date? Tell us

Claude Code in a dev container

A dev container holds the whole Claude Code process inside, not just shell commands. The feature adds the CLI to any container, a named volume keeps your login across rebuilds, and the reference container with a firewall and a regular user is the place where running without prompts is acceptable.

Level 6 · 0 / 4 lessons0%
In this lesson

In the sandbox lesson, Claude Code restricted shell commands. A goes further: it is a Docker container your editor connects to — on your computer or in a cloud service such as GitHub Codespaces. The whole Claude Code process lives inside it: the file-editing tools, MCP servers, hooks. Commands run in the container, and edits reach your through a mount.

Three layers

Each layer builds on the one before:

LayerWhat it gives you
The Claude Code featurethe CLI inside any dev container
A named volume at ~/.claudeyour login survives a rebuild
The reference containera regular user and a firewall — a place for running without prompts

Layer 1: the feature

The feature is added with one line in .devcontainer/devcontainer.json:

{
  "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"
}

The catch is the :1.0 tag. It pins the feature’s install script, not Claude Code: the feature installs the latest release, which then updates itself. postCreateCommand adds bubblewrap and socat — without them, the Bash sandbox does not work on Linux.

Layer 2: a login that stays

Log in to Claude Code, rebuild the container — and claude auth status returns code 1. A rebuild keeps the project folder but throws away the home folder, and ~/.claude with it. Codespaces is the same: after Rebuild Container, /workspaces is still there, but the login is gone.

The fix is a Docker named volume at ~/.claude, plus the CLAUDE_CONFIG_DIR with the same path. The volume lives separately from the container, so the login and settings in it survive a rebuild:

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

If the login still disappears, check that the volume’s target and CLAUDE_CONFIG_DIR name the same path.

Layer 3: the reference container

The Claude Code repository contains a reference .devcontainer/ of three files: devcontainer.json, Dockerfile and init-firewall.sh. It adds:

  • a regular user, node, instead of root;
  • a firewall: outbound traffic goes only to the addresses listed in init-firewall.sh.

This is the container the documentation supports for runs with --dangerously-skip-permissions. As root, the CLI does not accept that flag at all.

Before the first build:

  1. Read all three files. init-firewall.sh runs as root on every container start — as the postStartCommand.
  2. Add the login domains. Next to api.anthropic.com, the list must include claude.ai and platform.claude.com, or logging in and refreshing the login will hit the firewall. If you need PyPI or a private package registry, add those to the list too and rebuild.
  3. Pin the version. In the CLAUDE_CODE_VERSION build argument, replace latest with a specific version, and add "DISABLE_AUTOUPDATER": "1" to containerEnv.

Checking the firewall is simple: inside the container, a request to example.com should fail, and one to api.github.com should go through.

When everything checks out, one unattended run inside the container — with the same limits as in the level on running autonomously:

claude -p "Add a one-line description of the repository at the top of README.md" \
  --dangerously-skip-permissions --model sonnet --max-turns 10

Cleaning up

The volume outlives the container — and so does your login in it. When you are done, run claude auth logout inside the container, then delete the container and the volumes whose names start with claude-code-config- and claude-code-bashhistory- (docker volume ls, then docker volume rm). Delete a codespace separately: even stopped, it still takes up space.

Quick check

The Claude Code feature is added with the :1.0 tag. Which version of Claude Code will be in the container a month from now?

Careful

Practice in the terminal

Check your understanding

Answered 0/3
Mode:

What does the :1.0 tag on the ghcr.io/anthropics/devcontainer-features/claude-code feature pin?

Why does your Claude Code login disappear after a container rebuild, and how do you fix it?

You run claude --dangerously-skip-permissions in a container with the project mounted. What on your computer can be affected?

Finish the task in the terminal and answer the questions to complete the lesson.

📝 My notes

Saved automatically in this browser · shows up on the Notes page.

Task

Describe a dev container for the project: a base image, the Claude Code feature, and a named volume at ~/.claude that CLAUDE_CONFIG_DIR points to, so your login survives a rebuild.

Tab complete · ↑ history · Ctrl+L clear · help commands

  • Not done: The Claude Code feature is added to the container
  • Not done: A named volume is mounted at ~/.claude
  • Not done: CLAUDE_CONFIG_DIR points to the volume

Lesson Q&A

What does the :1.0 tag on the ghcr.io/anthropics/devcontainer-features/claude-code feature pin?

The feature's install script — Claude Code itself is installed at the latest version and then updates itself — The tag pins only the installer. To pin Claude Code itself, the reference container installs the version you want through the CLAUDE_CODE_VERSION build argument, and DISABLE_AUTOUPDATER=1 turns auto-update off.

Why does your Claude Code login disappear after a container rebuild, and how do you fix it?

A rebuild throws away the home folder along with ~/.claude; a named volume at ~/.claude and CLAUDE_CONFIG_DIR with the same path fix it — Docker keeps a volume separately from the container, so the login in it survives a rebuild. The volume's path and CLAUDE_CONFIG_DIR must match.

You run claude --dangerously-skip-permissions in a container with the project mounted. What on your computer can be affected?

The project's files, including .git and .devcontainer — the no-prompts mode writes to protected paths too, and the mount carries the edits to you — A modified .devcontainer is used at the next rebuild, and hooks in .git run at git commit on your own machine. That is why you read the diff before rebuilding and before committing.

The Claude Code feature is added with the :1.0 tag. Which version of Claude Code will be in the container a month from now?

The tag pins the installer, not the CLI. To keep the version fixed, you need CLAUDE_CODE_VERSION in the build and DISABLE_AUTOUPDATER=1.

Commands in this lesson

Terms in this lesson

Move between lessons with ← → · search with ⌘K

Written and reviewed by Mikhail Kuzmitskii