cd /news/developer-tools/persisting-claude-cli-login-between-… · home topics developer-tools article
[ARTICLE · art-95235] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Persisting Claude CLI Login Between Container Builds

A developer solved the problem of Claude Code CLI login state not persisting across devcontainer rebuilds by mounting a named Docker volume onto a directory and symlinking the dotfile into it, avoiding the broken file-to-file mount on Docker Desktop. The workaround ensures `~/.claude.json` survives image rebuilds without shadowing the entire home directory.

read2 min views1 publishedAug 13, 2026

Keep Claude Code's account/session login (~/.claude.json

) alive across

devcontainer rebuilds, instead of having to re-authenticate every time the

image is rebuilt.

Claude Code keeps two things on disk:

~/.claude/

— a directory, already persisted via a named Docker volume (claude-playwright-setup

).~/.claude.json

— a single Normally you'd just mount a named volume onto the whole folder the state

lives in, the same way .claude/

, .copilot/

, and .continue/

are already

handled. That's not an option here: .claude.json

isn't inside its own

subfolder, it sits directly in $HOME

alongside everything else

(.bashrc

, .ssh/

, .profile

, ...). Mounting a volume onto $HOME

itself

to catch one file would shadow all of that, so the file has to be persisted

on its own.

Mounting a named volume straight onto the file path

(claude-json-...:/home/container-user/.claude.json

) seems like the

next-simplest option, but it breaks on this Docker Desktop setup:

mount ... not a directory: Are you trying to mount a directory onto a file

A named volume's backing store is always a directory. Docker is supposed to

detect that the mount target is a single file and copy the image's file into

the volume so it ends up binding file-to-file. On this Docker Desktop that

detection fails — the volume comes up as an empty directory, and runc

then

tries to bind that directory onto the file path and crashes at container

start. This was confirmed by deleting the volume and rebuilding the image

from scratch, so it isn't a stale-cache artifact.

Never mount a volume directly onto a single file. Instead, mount it onto a

directory — the same shape already used for .claude

/.copilot

/.continue

— and symlink the dotfile into that directory from the Dockerfile.

Dockerfile.debian

:

USER container-user
....
RUN mkdir -p /home/container-user/.claude-json && \
    touch /home/container-user/.claude-json/claude.json && \
    ln -s /home/container-user/.claude-json/claude.json /home/container-user/.claude.json

docker-compose.yml

:

services:
  devcontainer:
    volumes:
      - claude-json-playwright-setup:/home/container-user/.claude-json

volumes:
  claude-json-playwright-setup:
    name: setup-playwright-playground-debian_claude-json-playwright-setup

** post-container-install.sh** — fix ownership on the new mount, same as the

sudo chown -R container-user:container-user /home/container-user/.claude \
                                            /home/container-user/.claude-json \
                                            /home/container-user/.copilot \
                                            ...

.claude/settings.json

and .claude/settings.local.json

also gained a few

permission entries (docker volume *

, docker run *

, docker compose *

,

docker history *

, and a find ... -iname *.copilot*

) needed to diagnose

and rebuild the container while working through this.

If an app ever persists the file via write-temp-then-rename (an atomic

write) instead of writing in place, the rename replaces the symlink with a

plain file inside the container's ephemeral layer. No crash — but

persistence silently stops working until the next image build recreates the

symlink. Worth checking if login state ever mysteriously stops surviving a

rebuild again.

── more in #developer-tools 4 stories · sorted by recency
── more on @claude code 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/persisting-claude-cl…] indexed:0 read:2min 2026-08-13 ·