Claude Code im Container: Podman, Docker und geteilte Setups
Wie du Claude Code in Podman (rootless/rootful) und Docker betreibst, Container und ~/.claude-Ordner zwischen mehreren Nutzern teilst und Rechte mit Gruppen, setgid und Default-ACLs sauber setzt.
von Jean Pierre Kolb ·
Claude Code läuft am schnellsten dort installiert, wo du arbeitest: direkt auf dem Host. Aber „direkt auf dem Host" ist nicht immer die beste Idee. Sobald du den Agenten unbeaufsichtigt arbeiten lässt, ihn an fremdem Code ansetzt oder ihn mehreren Menschen auf einer Maschine zur Verfügung stellen willst, wird ein Container von der Kür zur Pflicht. Dieser Artikel zeigt dir die ganze Bandbreite: vom offiziellen Devcontainer über selbstgebaute Podman- und Docker-Setups bis zu dem Szenario, das mich am meisten interessiert hat — eine Claude-Code-Installation, die sich mehrere Benutzerkonten auf demselben Rechner teilen, inklusive gemeinsam genutzter ~/.claude-Konfiguration.
Das ist bewusst ein einsteigerfreundlicher Rundumschlag. Wenn du schon Container-Profi bist, kannst du die Grundlagenkapitel überspringen und direkt zu den Rechte- und Sharing-Themen springen. Wenn nicht, nehme ich dich an die Hand: Jeder Begriff wird eingeordnet, jeder Befehl erklärt.
Warum Claude Code überhaupt in einen Container?
Claude Code ist ein agentisches Werkzeug. Es liest Dateien, führt Shell-Befehle aus, ruft Tools auf — und je weniger es dich dabei um Erlaubnis fragen muss, desto produktiver ist es, aber desto größer ist auch der Radius, den ein Fehler oder ein böswilliger Prompt anrichten kann. Genau hier setzt Containerisierung an. Sie zieht eine Grenze um das, was der Agent sehen, schreiben und erreichen kann.
Vier konkrete Gründe, warum sich der Aufwand lohnt:
- Reproduzierbarkeit. Ein Container-Image definiert die exakte Umgebung — Node-Version, Tools, Abhängigkeiten — für alle gleich. „Bei mir läuft's" hört auf, ein Argument zu sein.
- Isolation bei autonomem Betrieb. Erst eine Grenze um den ganzen Prozess macht Modi wie
--dangerously-skip-permissionsoder den unbeaufsichtigten Lauf vertretbar. Ohne Container ist dieser Schalter im Klartext ein Freibrief auf dein gesamtes Home-Verzeichnis. - Arbeit an nicht vertrautem Code. Ein fremdes Repository kann Prompt-Injection-Fallen enthalten. Im Container kann der Schaden das Projektverzeichnis und das, was die Netz-Policy erlaubt, kaum verlassen.
- Eine Installation für viele. Statt Claude Code in jedem Benutzerkonto einzeln zu installieren und zu pflegen, stellst du es einmal als Image bereit. Das ist der rote Faden der zweiten Artikelhälfte.
Anthropic empfiehlt Container ausdrücklich als zusätzliche Isolationsschicht und vergibt einen wichtigen Grundsatz gleich mit: Isolation senkt den Schaden eines Einbruchs, beseitigt das Risiko aber nicht. Was an die Anthropic-API geht, geht mit oder ohne Container an die API. Ein Container ist eine Wand, kein Zauber.
Wie das grundsätzlich aussieht
Bevor wir in Varianten einsteigen, das gemeinsame Grundmuster. Egal welcher Ansatz: Drei Dinge treffen im Container zusammen.
- Dein Projektverzeichnis wird per Bind-Mount in den Container gehängt. Der Container sieht deinen Code, und Änderungen, die Claude macht, erscheinen sofort in deinem echten Repository auf dem Host. Der Code „zieht nicht um", er wird nur durchgereicht.
- Claude Code selbst ist im Image installiert und läuft als Prozess innerhalb der Grenze. Alle Shell-Befehle, die der Agent absetzt, laufen im Container — nicht auf deinem Host.
- Der Zustand unter
~/.claude— Anmeldung, Einstellungen, Verlauf, Skills — liegt entweder in einem mitgemounteten Verzeichnis oder in einem Container-Volume, damit er einen Neustart überlebt.
Editoren wie VS Code, Cursor oder JetBrains, die den Dev-Containers-Standard unterstützen, klinken sich in genau diesen Container ein: Du editierst wie gewohnt in der Oberfläche, aber Terminal, Sprachserver und Build-Tools laufen drinnen. Ein reiner Terminal-Workflow (podman run … claude) funktioniert genauso — nur ohne IDE-Anbindung.
Merke dir die zwei beweglichen Teile: das Projekt (kommt vom Host rein, schreibbar) und die Config (~/.claude, persistiert). Fast alle Feinheiten in diesem Artikel drehen sich darum, wer mit welchen Rechten auf diese beiden Teile zugreifen darf.
Die Isolationsstufen im Überblick
Container sind nicht die einzige Möglichkeit, Claude Code einzuhegen — und nicht für jeden Zweck die richtige. Anthropic beschreibt eine ganze Leiter von Isolationsstufen, von leichtgewichtig bis maximal getrennt. Es lohnt sich, sie zu kennen, damit du nicht mit Kanonen auf Spatzen schießt:
| Ansatz | Was isoliert wird | Docker nötig? | Aufwand |
|---|---|---|---|
Bash-Sandbox (/sandbox) | Nur Bash-Befehle und ihre Kindprozesse | Nein | Minimal |
| Sandbox-Runtime | Der ganze Claude-Code-Prozess (Datei-Tools, MCP, Hooks) | Nein | Gering |
| Devcontainer | Komplette Entwicklungsumgebung | Ja | Mittel |
| Custom Container | Komplette Entwicklungsumgebung | Ja | Mittel–hoch |
| Virtuelle Maschine | Vollständiges Betriebssystem | Nein | Hoch |
| Claude Code on the web | Vollständiges OS, von Anthropic gehostet | Nein | Keiner (Abo nötig) |
Die ersten beiden laufen ohne Container direkt auf dem Host-Betriebssystem. Die Bash-Sandbox (eingebaut, aktivierbar mit /sandbox) nutzt OS-Primitive — bubblewrap unter Linux und WSL2, Seatbelt unter macOS — und beschränkt nur die Shell-Befehle. Datei-Tools, MCP-Server und Hooks laufen weiter ungebremst. Sie ist ideal, um im Alltag auf der eigenen Maschine weniger Erlaubnis-Prompts zu sehen, aber sie reicht für vollautonomen Betrieb nicht aus.
Die Sandbox-Runtime (@anthropic-ai/sandbox-runtime, ein Forschungs-Preview) packt denselben bubblewrap/Seatbelt-Käfig um den gesamten Prozess. Sie verweigert standardmäßig alle Schreib- und Netzzugriffe; du erlaubst in ~/.srt-settings.json gezielt dein Projektverzeichnis, die Config-Pfade ~/.claude und ~/.claude.json sowie die nötigen Domains. Gestartet wird mit npx @anthropic-ai/sandbox-runtime claude.
Alles ab Devcontainer abwärts steckt Claude Code in einen Container oder eine VM. Genau diese Stufen sind das Thema dieses Artikels. Die VM bietet die stärkste Trennung (eigener Kernel) und ist die Wahl für wirklich nicht vertrauenswürdigen Code; Claude Code on the web ist eine von Anthropic gehostete VM mit Egress-Proxy für alle, die gar keine lokale Umgebung aufsetzen wollen.
Merksatz: Permission-Modi (was darf laufen, fragt es vorher?) und Isolation (was kann ein Befehl erreichen, wenn er läuft?) sind zwei verschiedene Dinge, die zusammenarbeiten.
--dangerously-skip-permissionsschaltet die Einzelfreigabe ab — dann ist die Isolationsgrenze das Einzige, was den Agenten noch begrenzt. Diesen Schalter deshalb nur in Container, VM oder Sandbox-Runtime verwenden.
Grundbegriffe für Einsteiger
Vier Begriffe begegnen dir ab hier ständig. Wenn du sie schon kennst, spring zum nächsten Kapitel.
Rootless vs. rootful. Klassisch (rootful) läuft der Container-Daemon als root, und Prozesse im Container sind echtes root auf dem Host — eine bekannte Angriffsfläche. Rootless bedeutet: Container laufen unter deinem normalen Benutzerkonto, ganz ohne Daemon mit Root-Rechten. Podman kann beides, ist aber für den rootless-Betrieb gebaut; Docker ist traditionell rootful (es gibt auch einen rootless-Modus, der hier aber Nebenschauplatz ist).
User-Namespaces. Der Mechanismus hinter rootless. Ein User-Namespace bildet Benutzer-IDs im Container auf andere IDs auf dem Host ab. root (UID 0) im Container ist dann z. B. dein Host-User (UID 1000) — drinnen mächtig, draußen harmlos. Diese Abbildung ist der Grund, warum Dateirechte zwischen Host und Container manchmal überraschen.
UID/GID. Linux kennt Benutzer und Gruppen nur als Zahlen: die User-ID (UID) und die Group-ID (GID). Namen wie alice oder shared sind nur Etiketten, die über /etc/passwd bzw. /etc/group auf diese Zahlen zeigen. Für Dateirechte zählt immer die Zahl. Das wird gleich wichtig, weil ein Gruppenname, den der Host kennt, im Container-Image oft gar nicht existiert — die numerische GID dagegen funktioniert überall.
Bind-Mount vs. Named Volume. Ein Bind-Mount hängt einen konkreten Host-Pfad in den Container (-v /home/alice/projekt:/workspace) — ideal für deinen Code und für geteilte Config. Ein Named Volume ist ein von der Container-Engine verwalteter Speicher ohne festen Host-Pfad (-v claude-config:/home/node/.claude) — ideal, um Zustand über Container-Neubauten hinweg zu erhalten, etwa im Devcontainer.
Ansatz A — Der offizielle Devcontainer
Anthropic liefert einen fertigen Weg, Claude Code in einen Dev Container zu bringen. Das ist der bequemste Einstieg, wenn du mit VS Code, Codespaces oder einer JetBrains-IDE arbeitest, und gleichzeitig die Referenz, an der wir die selbstgebauten Setups messen.
Im einfachsten Fall ist es ein Dreizeiler. Du legst .devcontainer/devcontainer.json an und ziehst das Claude Code Dev Container Feature herein:
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/anthropics/devcontainer-features/claude-code:1.0": {}
}
}Der Versions-Tag :1.0 pinnt das Install-Skript des Features, nicht die Claude-Code-Version — das Feature installiert immer das aktuelle Claude Code, und das aktualisiert sich im Container per Default selbst. „Rebuild Container", claude im integrierten Terminal starten, im Browser anmelden — fertig.
Drei Bausteine machen aus diesem Minimal-Setup eine ernstzunehmende Isolation; sie stecken im Referenz-Container des anthropics/claude-code-Repos (drei Dateien: devcontainer.json, Dockerfile, init-firewall.sh):
1. Persistente Anmeldung. Das Home-Verzeichnis des Containers wird bei jedem Rebuild verworfen — du müsstest dich jedes Mal neu anmelden. Ein Named Volume auf ~/.claude löst das:
"mounts": [
"source=claude-code-config,target=/home/node/.claude,type=volume"
]/home/node ist das Home des Standard-Users node im Image. Willst du den Zustand pro Projekt trennen statt ihn über alle Repos zu teilen, nimmst du source=claude-code-config-${devcontainerId}. Liegt das Volume woanders als unter ~/.claude, setzt du CLAUDE_CONFIG_DIR auf den Mount-Pfad.
2. Netz-Egress-Firewall. Der Referenz-Container bringt ein Skript init-firewall.sh mit, das per iptables allen ausgehenden Verkehr blockt — bis auf die Domains, die Claude Code und deine Tools brauchen (Standard ist „default deny"). Eine Firewall im Container zu betreiben braucht Extra-Rechte, deshalb gibt die Referenz über runArgs die Capabilities NET_ADMIN und NET_RAW mit. Beides ist für Claude Code selbst nicht zwingend — du kannst es weglassen und dich auf eigene Netzkontrollen verlassen.
3. Non-Root-User. Der Container läuft als Nicht-Root-Benutzer (node), und das ist die Voraussetzung für den entscheidenden Komfort: Weil die Befehlsausführung im Container eingehegt ist und nicht als root läuft, darfst du --dangerously-skip-permissions für den unbeaufsichtigten Betrieb setzen. Die CLI verweigert diesen Schalter, wenn sie als root gestartet wird — remoteUser muss also ein Nicht-Root-Konto sein.
Organisations-Policy lässt sich elegant zentral verankern: Claude Code liest unter Linux /etc/claude-code/managed-settings.json mit höchster Priorität (überschreibt alles aus ~/.claude oder dem Projekt). Per containerEnv setzt du globale Variablen, etwa CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC und DISABLE_AUTOUPDATER.
Wo der Devcontainer aufhört
Der offizielle Devcontainer ist exzellent für einen Entwickler an einem Projekt mit einer IDE. Genau dort liegen aber auch seine Grenzen, und die sind der Grund für den Rest dieses Artikels:
- Er ist an einen Editor gebunden. Reiner Terminal-Betrieb, Cron-Jobs, ein gemeinsamer Server-Login ohne IDE — dafür ist er nicht gedacht.
- Er denkt pro Nutzer und pro Projekt, nicht „eine Installation, viele Menschen". Das Volume
claude-code-configgehört dem Container, nicht einer geteilten Host-Gruppe. - Anthropic warnt ausdrücklich: Mit
--dangerously-skip-permissionskann ein bösartiges Projekt alles exfiltrieren, was im Container erreichbar ist — auch die in~/.claudegespeicherten Anmeldedaten. Mounte deshalb keine Host-Secrets wie~/.sshoder Cloud-Credential-Dateien hinein.
Den letzten Punkt nimm ernst: Er ist der Kern des Sharing-Problems, das wir gleich angehen. Wer Zugriff auf ~/.claude hat, hat potenziell Zugriff auf das OAuth-Token.
Ansatz B — Rootless Podman
Podman im rootless-Modus ist mein bevorzugter Weg für selbstgebaute Setups: kein Daemon, keine Root-Rechte, Container laufen unter deinem normalen Konto. Du brauchst keine IDE und keinen Devcontainer-Standard — ein podman run genügt.
Ein minimales Dockerfile (Podman liest dasselbe Format):
FROM node:22-bookworm-slim
# Create a non-root user; Claude Code refuses --dangerously-skip-permissions as root
RUN useradd --create-home --shell /bin/bash dev
# Install Claude Code globally, pinned for reproducible builds
RUN npm install -g @anthropic-ai/claude-code@2.0.0
USER dev
WORKDIR /workspace
ENTRYPOINT ["claude"]Bauen und starten:
podman build -t claude-code:local .
podman run --rm -it \
-v "$PWD":/workspace:Z \
-v "$HOME/.claude":/home/dev/.claude:Z \
claude-code:localZwei Details, die Einsteiger oft stolpern lassen:
- Das
:Zam Mount weist Podman an, das SELinux-Label des Verzeichnisses passend umzuschreiben. Auf SELinux-Systemen (Fedora, RHEL) bekommst du sonst „Permission denied", obwohl die Unix-Rechte stimmen. Auf Systemen ohne SELinux (viele Debian/Ubuntu-Installationen, WSL2) ist:Zwirkungslos, aber harmlos. - Du mountest hier dein eigenes
~/.claudehinein. Für den Single-User-Fall ist das genau richtig. Für den geteilten Mehrbenutzer-Fall ändern wir das gleich grundlegend.
Der eigentliche rootless-Stolperstein ist die Gruppenzugehörigkeit. Standardmäßig bildet Podman die Supplementär-Gruppen deines Host-Users im User-Namespace auf nobody ab — der Container verliert also jede zusätzliche Gruppenmitgliedschaft. Sobald du auf ein gruppen-geschütztes Verzeichnis schreiben willst (genau unser Sharing-Szenario), brauchst du:
podman run --group-add keep-groups ...keep-groups (technisch die Annotation run.oci.keep_original_groups=1) behält die Host-GIDs für die Rechteprüfung am Dateisystem bei. Ist dein Host-User Mitglied der geteilten Gruppe, darf der Container-Prozess dann schreiben. Wir kommen in Kapitel 11 darauf zurück.
Praxis · WSL2: Unter WSL2 läuft Podman rootless problemlos. SELinux ist dort nicht aktiv, also kannst du
:Zweglassen. Achte aber darauf, dass dein Projekt und~/.claudeim Linux-Dateisystem (/home/...) liegen, nicht unter/mnt/c/...— Mounts über die Windows-Grenze sind langsam und ihre Rechte-Semantik (kein echteschmod/ACL) bricht alles, was in diesem Artikel über Gruppen und ACLs steht.
Ansatz C — Rootful Docker
Bei klassischem, rootful Docker ist die Lage anders — und in einem Punkt heikler. Container-GIDs mappen hier direkt auf Host-GIDs. Das macht das Teilen einer Gruppe einerseits einfacher (keine nobody-Abbildung), birgt andererseits die größte Falle des ganzen Themas: Wenn der Container-Prozess als root schreibt, gehören die erzeugten Dateien auf dem Host root:root — und durchbrechen jedes Gruppenmodell.
Die saubere Variante lässt den Prozess als deinen User laufen und gibt die geteilte Gruppe als numerische GID mit (der Gruppenname existiert im Image meist nicht):
docker run --rm -it \
--user "$(id -u):$(id -g)" \
--group-add 1234 \
-v "$PWD":/workspace \
-v "$HOME/.claude":/home/dev/.claude \
claude-code:localMit Docker Compose sieht dasselbe so aus:
services:
claude:
image: claude-code:local
user: "1000:1000" # deine Host-UID:GID
group_add:
- "1234" # numerische GID der Gruppe 'shared'
volumes:
- ./:/workspace
- ${HOME}/.claude:/home/dev/.claude
stdin_open: true
tty: trueDie 1234 ermittelst du auf dem Host mit getent group shared | cut -d: -f3. Schreib sie wirklich numerisch hin — verlässt du dich auf den Namen, scheitert es, weil das schlanke Image keine Zeile shared in /etc/group hat.
Praxis · DDEV: Wenn du mit DDEV arbeitest, ist dieser Teil schon gelöst. DDEV mappt den Container-User ohnehin auf deinen Host-User. Solange das gemountete Verzeichnis die in Kapitel 11 beschriebenen Rechte trägt, kannst du Claude Code dort ohne weitere
--user-/group_add-Akrobatik betreiben.
Kernszenario: Eine Installation, viele Nutzer
Jetzt zum eigentlichen Ziel. Stell dir einen gemeinsamen Entwicklungs-Server vor — oder schlicht einen Familien- oder Team-Rechner — auf dem mehrere Menschen mit eigenen Linux-Konten arbeiten. Du willst Claude Code nicht in jedem Konto einzeln installieren, aktuell halten und konfigurieren. Stattdessen:
- Ein Image, zentral gepflegt. Du baust
claude-code:localeinmal (oder ziehst es aus einer internen Registry). Aktualisieren heißt: Image neu bauen, nicht n Konten anfassen. Version-Pinning im Dockerfile macht die Umgebung für alle identisch. - Jeder Nutzer startet denselben Container über sein eigenes Konto. Bei rootless Podman läuft der Container unter dem jeweiligen Host-User — die Trennung der Konten bleibt also erhalten, obwohl die Software geteilt ist.
- Geteilt wird die Installation und (Teile der) Konfiguration, nicht die Identität. Das ist die wichtige Unterscheidung: Eine gemeinsame Code-Basis ja, eine gemeinsame Anmeldung nur mit Bedacht (siehe Kapitel 10).
Der Knackpunkt liegt nicht im Image — das ist trivial zu teilen — sondern in den gemeinsam genutzten Verzeichnissen auf dem Host: ein geteilter Skill-/Command-/Settings-Bestand, vielleicht ein gemeinsames Projekt-Verzeichnis. Mehrere Konten, die in dieselben Dateien schreiben sollen, ohne sich gegenseitig auszusperren — das ist ein klassisches Unix-Rechteproblem, und es löst sich nicht mit „einfach alle in eine Gruppe stecken". Warum, und wie es richtig geht, klären die nächsten beiden Kapitel.
~/.claude gemeinsam teilen — aber richtig
Der Reiz ist groß, einfach das ganze ~/.claude-Verzeichnis zwischen allen zu teilen: einmal anmelden, einmal Skills pflegen, alle profitieren. Bevor du das tust, musst du wissen, was in diesem Verzeichnis steckt — denn nicht alles darf gemeinsam genutzt werden.
~/.claude (verschiebbar über CLAUDE_CONFIG_DIR) enthält grob drei Sorten von Inhalten:
Unkritisch und gut teilbar (Konfiguration & Erweiterungen):
settings.json— Berechtigungen, Hooks, Modell-Defaults, UmgebungsvariablenCLAUDE.md— deine globalen Anweisungen über alle Projekteskills/,commands/,agents/,rules/,output-styles/,workflows/— wiederverwendbare Erweiterungenplugins/— installierte Plugins und Marketplacesthemes/,keybindings.json— Optik und Tastenkürzel
Pro Nutzer und sensibel (Identität & Verlauf) — NICHT teilen:
.credentials.json— das OAuth-Token. Unter Linux liegt es als Datei, nur durch Dateirechte geschützt, nicht verschlüsselt. Wer es lesen kann, kann sich als dieser Account ausgeben.projects/<projekt>/<session>.jsonl— die Session-Transkripte. Hier landet alles, was Claude während einer Sitzung gelesen hat — liest ein Tool eine.envoder gibt ein Befehl ein Geheimnis aus, steht dieser Wert im Transkript.history.jsonl— deine Prompt-Historie.claude.json(im Home, neben dem Verzeichnis) — App-Zustand und UI-Präferenzenshell-snapshots/,file-history/— flüchtiger Sitzungszustand und Pre-Edit-Snapshots
Daraus folgen zwei legitime Wege — und du musst dich bewusst für einen entscheiden.
Weg 1 (empfohlen): Config teilen, Identität trennen
Die saubere Aufteilung: Du teilst nur die unkritische Konfiguration read-only und gibst jedem Nutzer ein eigenes, beschreibbares ~/.claude für Anmeldung, Transkripte und Verlauf.
Praktisch heißt das: Der geteilte Bestand (Skills, Commands, Agents, eine Basis-settings.json) liegt in einem gemeinsamen Verzeichnis wie /srv/claude-shared/ und wird read-only in den Container gemountet. Der schreibbare, private Teil liegt pro Nutzer und wird über CLAUDE_CONFIG_DIR als Hauptverzeichnis gesetzt:
podman run --rm -it \
-e CLAUDE_CONFIG_DIR=/home/dev/.claude \
-v "$HOME/.claude":/home/dev/.claude:Z \
-v /srv/claude-shared/skills:/home/dev/.claude/skills:ro \
-v /srv/claude-shared/commands:/home/dev/.claude/commands:ro \
-v /srv/claude-shared/agents:/home/dev/.claude/agents:ro \
claude-code:localJeder meldet sich einmal mit dem eigenen Konto an (.credentials.json bleibt privat), niemand sieht die Transkripte der anderen, aber alle teilen sich denselben kuratierten Skill- und Command-Bestand. Aktualisiert ein Admin einen Skill in /srv/claude-shared/, haben ihn beim nächsten Start alle. Das read-only :ro verhindert, dass der Agent den geteilten Bestand versehentlich verändert.
Weg 2: Komplette ~/.claude teilen — mit offenen Augen
Es gibt Situationen, in denen ein gemeinsames Konto gewollt ist — etwa ein dediziertes Team-/Service-Konto mit eigenem Abo, das mehrere Personen unbeaufsichtigt nutzen. Dann teilst du das ganze ~/.claude als einen beschreibbaren Mount (die Rechte dafür baust du in Kapitel 11). Das funktioniert technisch — aber kauf es dir mit klarem Blick auf die Risiken ein:
- Geteiltes Token = geteilte Identität. Alle Aktionen laufen unter demselben Account; Nachvollziehbarkeit, wer was getan hat, ist dahin. Das Token liegt unverschlüsselt und ist für jeden mit Zugriff lesbar.
- Transkripte für alle. Jede
projects/.../*.jsonlist für alle Gruppenmitglieder sichtbar. Liest Claude in irgendeiner Sitzung ein Geheimnis, sehen es alle. - Gleichzeitigkeit. Mehrere parallele Sitzungen auf demselben Zustandsverzeichnis können sich in die Quere kommen (Verlauf, Snapshots). Für echten Parallelbetrieb ist Weg 1 ohnehin robuster.
Wenn du Weg 2 gehst, dann bewusst und eng: ein eigens dafür angelegtes Konto, ein scharfer Egress-Filter (Kapitel 12), und auf keinen Fall vermischt mit den privaten Home-Verzeichnissen echter Personen. Für die meisten Setups ist Weg 1 die richtige Wahl; Weg 2 ist das Werkzeug für den Sonderfall „eine Maschine, ein Bot-Konto, mehrere Bediener".
Rechte & Gruppen im Detail
Jetzt der technische Kern — und die Stelle, an der die meisten „nur eine Gruppe"-Lösungen scheitern. Eine gemeinsame Gruppe ist die richtige Grundlage, reicht aber allein nicht: Neu erstellte Dateien bekommen standardmäßig die primäre Gruppe ihres Erzeugers und, dank umask 022, kein Gruppen-Schreibrecht. Damit ein geteiltes Verzeichnis dauerhaft funktioniert, brauchst du drei Bausteine auf dem Host plus eine separate Behandlung im Container.
Basis: Gruppe + setgid + Default-ACLs
# 1. Gruppe anlegen und Nutzer aufnehmen
sudo groupadd shared
sudo usermod -aG shared alice
sudo usermod -aG shared bob
# Note: membership takes effect only after re-login (or `newgrp shared`)
# 2. Verzeichnis mit setgid-Bit
sudo mkdir -p /srv/shared
sudo chown root:shared /srv/shared
sudo chmod 2775 /srv/shared # leading 2 = setgid
# 3. Default-ACLs (der eigentliche Schlüssel)
sudo setfacl -R -m g:shared:rwx /srv/shared # existing entries
sudo setfacl -R -d -m g:shared:rwx /srv/shared # default for new entriesWas hier passiert, und warum jeder Schritt nötig ist:
Das setgid-Bit (die führende 2 in 2775) sorgt dafür, dass neue Dateien und Unterordner die Gruppe shared erben — statt der primären Gruppe ihres Erzeugers. Ohne setgid würde Alices neue Datei der Gruppe alice gehören, und Bob stünde außen vor.
Die Default-ACL ist der eigentliche Schlüssel. Sie sorgt dafür, dass neue Dateien gruppen-schreibbar sind — unabhängig von der umask des jeweiligen Nutzers. Genau hier scheitern die einfachen Lösungen: Die umask ist eine pro-Prozess- bzw. pro-Login-Einstellung. Du müsstest sie für jeden Nutzer und jeden Dienst auf 002 erzwingen — fragil und leicht zu vergessen. Eine Default-ACL liegt dagegen am Dateisystem und gilt universell, egal mit welcher umask jemand schreibt. Deshalb ist setgid + Default-ACL robuster als setgid + globale umask.
Die Container-Brücke
Das Verzeichnis ist damit auf dem Host korrekt. Ob ein Container hineinschreiben kann, hängt aber davon ab, mit welcher UID/GID der Prozess im Host-Namespace landet. Hier trennen sich Podman und Docker, wie schon angedeutet:
Rootless Podman mappt Host-Supplementärgruppen standardmäßig auf nobody — der Container verliert die shared-Mitgliedschaft. Lösung:
podman run --group-add keep-groups ...keep-groups behält die Host-GIDs für die Dateisystem-Rechteprüfung. Da dein Host-User in shared ist, darf der Container-Prozess dann schreiben. Beachte: Neu erzeugte Dateien gehören weiterhin der gemappten UID — aber die Default-ACL fängt das Schreibrecht der Gruppe ab.
Rootful Docker mappt Container-GIDs direkt auf Host-GIDs. Gib die numerische GID als Supplementärgruppe mit:
services:
app:
group_add:
- "1234" # numerische GID von 'shared'bzw. docker run --group-add 1234. Und noch einmal die Warnung, weil sie hier am meisten kostet: Schreibt der Container-Prozess als root, landen die Dateien als root:root auf dem Host und durchbrechen das Modell. Entweder den Prozess als deinen User laufen lassen (--user) oder im Image umask/GID passend setzen.
Zwei Praxis-Fallen
Selbst mit perfekt gesetzten ACLs gibt es zwei Wege, sich das Modell unbemerkt zu zerschießen:
- Werkzeuge, die Rechte „mitschleppen".
cp -p,rsync -aoder eintar-Restore übernehmen Original-Eigentümer und -Rechte und umgehen damit die Vererbung. Befüllst du das geteilte Verzeichnis so, ziehst du die alten, falschen Rechte mit herein. Entweder bewusst ohne Permission-Preservation arbeiten (cpohne-p,rsyncohne-abzw. mit--no-perms --no-owner --no-group) oder hinterhersetfacl/chgrpnachziehen. - Programme, die ihre Dateien selbst auf
0600setzen. Manche Tools erzwingen restriktive Rechte auf ihre eigenen Dateien und überschreiben damit die ACL-Defaults — von außen nicht verhinderbar. Das ist kein theoretischer Fall: Genau so verhält sich Claude Code mit.credentials.json. Es ist gut, dass das Token eng bleibt — aber es bestätigt, warum du Anmeldedaten nach Weg 1 ohnehin nicht über die Gruppe teilst, sondern pro Nutzer hältst.
Sicherheit & Threat-Model
Container geben ein trügerisches Gefühl von Sicherheit, wenn man die Grenzen nicht kennt. Die wichtigsten Punkte, gebündelt:
- Credentials sind das Kronjuwel. Das OAuth-Token in
~/.claude/.credentials.jsonliegt unter Linux unverschlüsselt, nur durch Dateirechte geschützt. Mit--dangerously-skip-permissionskann ein bösartiges Repo alles im Container Erreichbare exfiltrieren — auch dieses Token. Konsequenz: Token pro Nutzer, niemals in einen Mount legen, auf den fremder Code mit weiten Rechten zugreift. --dangerously-skip-permissionsnur in einer Grenze. Container, VM oder Sandbox-Runtime — nie blank auf dem Host. Willst du weniger Prompts ohne die Sicherheitsprüfungen abzuschalten, nutze stattdessen den Auto-Mode: Ein Klassifizierer prüft jede Aktion, statt blind durchzuwinken.- Netz-Egress einschränken. Die wirksamste Einzelmaßnahme für unbeaufsichtigten Betrieb. Die
init-firewall.shder Referenz erlaubt nur die nötigen Domains. Selbst wenn der Agent kompromittiert wird, kann er Daten nur dorthin schicken, wohin die Policy ihn lässt. - Keine Host-Secrets mounten.
~/.ssh, Cloud-Credential-Dateien, Keychains haben im Container nichts zu suchen. Brauchst du Zugriff, nutze kurzlebige, eng begrenzte Tokens statt der dauerhaften Schlüssel. - Nicht vertrauenswürdiger Code gehört in eine VM — oder in Claude Code on the web. Ein Container teilt sich den Kernel mit dem Host; für echten „ich kenne diesen Code nicht"-Betrieb ist die kernel-getrennte VM die ehrlichere Wahl.
Und der Grundsatz, der über allem steht: Isolation reduziert den Schaden, sie beseitigt das Risiko nicht. Prüfe weiterhin, was der Agent tut.
Entscheidungshilfe
Welcher Ansatz für welches Ziel? Die Kurzfassung:
| Du willst … | Nimm … |
|---|---|
| Im Alltag auf der eigenen Maschine weniger Prompts | Bash-Sandbox (/sandbox) |
| MCP/Hooks zusätzlich isolieren, ohne Docker | Sandbox-Runtime |
Unbeaufsichtigt mit --dangerously-skip-permissions arbeiten | Devcontainer/Container mit Egress-Firewall |
| Eine teamweite, standardisierte Umgebung | Devcontainer ins Repo committen |
| An einem nicht vertrauenswürdigen Repo arbeiten | VM oder Claude Code on the web |
| Eine Installation für viele Nutzer | Systemweites Image + geteilte Gruppe (Kap. 9–11) |
| Auf einem Windows-Host arbeiten | Container/VM oder Bash-Sandbox in WSL2 |
Für das Mehrbenutzer-Ziel heißt das konkret: rootless Podman als Engine, ein zentral gepflegtes, versions-gepinntes Image, die setgid + Default-ACL-Basis auf dem geteilten Verzeichnis, --group-add keep-groups beim Start und Weg 1 beim ~/.claude-Sharing (Config geteilt, Identität pro Nutzer).
Fazit
Claude Code im Container ist kein Selbstzweck, sondern die Voraussetzung dafür, dem Agenten mehr Autonomie zu geben, ohne die Kontrolle zu verlieren. Der offizielle Devcontainer ist der schnellste Einstieg für die IDE-Arbeit; rootless Podman und rootful Docker geben dir die Freiheit, eigene Mehrbenutzer-Setups zu bauen.
Der eigentliche Hebel beim Teilen liegt nicht in der Container-Engine, sondern im Dateisystem: setgid für die Gruppenvererbung, Default-ACLs für das Schreibrecht unabhängig von der umask, und je nach Engine keep-groups (Podman) oder die numerische group_add (Docker) als Brücke in den Container. Trenne dabei konsequent, was teilbar ist (Skills, Commands, Settings) von dem, was es nicht ist (Token, Transkripte). Dann teilen sich beliebig viele Konten eine einzige, zentral gepflegte Installation — sauber, nachvollziehbar und ohne dass irgendwer mehr Rechte hat, als er braucht.
Wenn du tiefer in die Werkzeuge einsteigen willst: die Cheat-Sheets zu Podman, Docker und Docker Compose liegen hier in der Datenbank, und der Docker/Podman Composer hilft beim Umschreiben zwischen run-Befehlen und Compose-Dateien.