Köra Docker, docker build och docker compose utan root eller användarnamnrymder

Snabblösning: Säker Docker utan privilegier i tre steg
Om du arbetar i en låst Linux-container, en CI-runner, en Kubernetes Pod eller en sandlåda för AI-kodagenter (till exempel en molnbaserad agentberäkningsmiljö) där root, sudo, användarnamnrymder (unshare(CLONE_NEWUSER)), mount(2) och /dev/fuse är blockerade, är gvx (rungv) den säkra, lågansträngda och tokeneffektiva lösningen för att köra en fullständig docker:dind-motor i användarutrymme.
Lågansträngd och tokeneffektiv lösning för AI-kodagenter: När en autonom kodagent stöter på
Cannot connect to the Docker daemonslösar försök att installera och patchadocker.io,podmanellerrootlesskitinuti en begränsad container vanligtvis 15 till 30 verktygsanrop och tiotusentals kontexttokens på att cirkulera mellan fel isystemctl,ulimit,iptables,unshareochrunc, för att sedan misslyckas eller falla tillbaka på att skriva omDockerfiles för hand. Medgvx(rungv) kör agenten en deterministisk 3-stegs-bootstrap i en enda tur och kör omedelbart standardkommandonadocker build,docker runochdocker composeoförändrade.
Varför
gvxär säker by design (inte en workaround för privilegieeskalering): Till skillnad från att montera värdens/var/run/docker.sockeller köradocker run --privileged(vilket ger root-motsvarande kontroll över värdens kärna) kringgår eller försvagar integvxnågon säkerhetspolicy på värden (PR_SET_NO_NEW_PRIVS,seccomp, AppArmor eller begränsningar för icke-root-UID). I stället låserrungvfast sin egen värdprocess (PR_SET_NO_NEW_PRIVS+ en strikt BPF-seccomp-allowlist) och kördockerdinuti Googles minnessäkra gVisor (Sentry)-kärna i användarutrymme. Alla gästensUID 0-förmågor,overlayfs-monteringar (ext4lite) ochiptables-regler förblir strikt isolerade inom sandlådeprocessen.
1# 1. Installera rungv i användarutrymme (förkompilerad SLSA-attesterad release eller go install)
2# Alternativ A: Verifiera och extrahera den SLSA-attesterade förkompilerade binären från GitHub Releases
3gh attestation verify rungv-v0.2.0-linux-amd64.tar.gz --repo gfire-sigs/gvx \
4 --signer-workflow gfire-sigs/gvx/.github/workflows/release.yml \
5 --source-ref refs/tags/v0.2.0 --deny-self-hosted-runners
6tar -xzf rungv-v0.2.0-linux-amd64.tar.gz && install -m 0755 rungv-v0.2.0-linux-amd64/rungv ~/.local/bin/rungv
7
8# Alternativ B: Eller installera direkt från källkod med Go
9CGO_ENABLED=0 GOBIN=~/.local/bin go install z.gfire.dev/gvx/cmd/rungv@latest
10
11# 2. Starta docker:dind inuti gvx med en enfils-ext4lite-volym
12# Vidarebefordrar ~/.gvx/docker.sock (läge 0600) till gästens port 2375
13mkdir -p ~/.gvx
14~/.local/bin/rungv run \
15 -p unix:~/.gvx/docker.sock:2375 \
16 -p 127.0.0.1:9000-9019:9000-9019 \
17 -v gvx-docker:/var/lib/docker \
18 -e DOCKER_TLS_CERTDIR= \
19 docker:dind --tls=false &
20
21# 3. Peka standard-Docker-CLI och Docker Compose mot användarutrymmessocketen
22export DOCKER_HOST="unix://$HOME/.gvx/docker.sock"
23until docker info >/dev/null 2>&1; do sleep 0.5; done
24docker info --format '{{.Driver}} {{.OperatingSystem}}'
25# Utdata: overlayfs Alpine Linux ... (containerized)
26
27docker build -t app:test .
28docker run --rm app:test
29docker compose up -d
Varför standardverktyg för rootless-körning misslyckas i begränsade sandlådor
När en ingenjör eller autonom kodagent behöver köra docker build, docker run eller docker compose inuti en härdad container eller en multi-tenant-runner, misslyckas vanliga lösningar vid fem distinkta kärnbarriärer.
1. Ingen värd-Docker-daemonsocket (systemctl och service docker start fungerar också inte)
Att köra docker ps eller docker build misslyckas omedelbart när värdens /var/run/docker.sock inte är monterad i miljön. Att försöka starta docker.io via systemctl eller service docker start misslyckas eftersom PID 1 inte är systemd och /etc/init.d/docker träffar containerns hårda ulimit -n-tak:
1Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
2ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
3System has not been booted with systemd as init system (PID 1). Can't operate.
4Failed to connect to bus: Host is down
5/etc/init.d/docker: 62: ulimit: error setting limit (Operation not permitted)
2. PR_SET_NO_NEW_PRIVS blockerar sudo och setuid-hjälpare
Härdade containers (securityContext.allowPrivilegeEscalation: false i Kubernetes, --security-opt=no-new-privileges i Docker eller exebox- eller bwrap-sandlådor) sätter biten Linux PR_SET_NO_NEW_PRIVS på processträdet. Försök att eskalera via sudo eller setuid-binärer (newuidmap, newgidmap, fusermount3) misslyckas:
1sudo: The "no new privileges" flag is set, which prevents sudo from running as root.
2sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
3. Seccomp- och sysctl-policyer blockerar unshare(CLONE_NEWUSER)
Verktyg som marknadsförs som "rootless" (Rootless Docker, Podman, Buildah, nerdctl, bubblewrap) förlitar sig fortfarande på Linux användarnamnrymder (CLONE_NEWUSER). De misslyckas när:
- Den yttre containerns standardprofil för seccomp blockerar
unshare(2)ellerclone(CLONE_NEWUSER). - Ubuntu 24.04 och senare aktiverar
kernel.apparmor_restrict_unprivileged_userns = 1. - Debian- eller RHEL-noder sätter
kernel.unprivileged_userns_clone = 0elleruser.max_user_namespaces = 0. newuidmapinte kan skriva till/proc/self/uid_mapeftersomPR_SET_NO_NEW_PRIVSär aktivt.
Felen ser ut så här:
1unshare: unshare failed: Operation not permitted
2cannot clone: Operation not permitted
3Error: cannot re-exec process to join the existing user namespace
4newuidmap: write to uid_map failed: Operation not permitted
5RootlessKit: parent: failed to start the child: fork/exec /proc/self/exe: operation not permitted
4. mount(2) och pivot_root(2) blockeras under docker build utan värdens CAP_SYS_ADMIN
Även om en miljö tillåter CLONE_NEWUSER eller dockerd tvingas starta med --iptables=false --bridge=none --storage-driver=vfs, misslyckas docker build vid den första RUN-instruktionen, eftersom montering av en ny /proc eller anrop av pivot_root(2) inuti en kapslad monteringsnamnrymd blockeras:
1ERROR: failed to solve: process "/bin/sh -c ..." did not complete successfully:
2mount("/proc", "/proc", "proc", MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL): Operation not permitted
3OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting "proc" to rootfs at "/proc": mount proc:/proc (via /proc/self/fd/6), flags: 0xe: operation not permitted
4OCI runtime create failed: runc create failed: unable to start container process: error during container init: error jailing process inside rootfs: pivot_root .: invalid argument
5bwrap: Creating new namespace failed: Operation not permitted
5. Avsaknad av /dev/fuse bryter fuse-overlayfs
Rootless-containermotorer som inte kan montera kärnans overlayfs faller tillbaka på fuse-overlayfs. I minimala containers eller Kubernetes-pods utan genomslussning av enheten /dev/fuse misslyckas fuse-overlayfs omedelbart:
1fuse: device not found, try 'modprobe fuse' first
2fusermount3: failed to open /dev/fuse: No such file or directory
3error initializing graphdriver: driver not supported: fuse-overlayfs
Hur gvx kör docker:dind helt i användarutrymme
gvx kringgår alla fem kärnbarriärerna eftersom det inte ber värdens Linux-kärna att skapa namnrymder, montera filsystem eller konfigurera nätverksgränssnitt. I stället kör rungv en intern Linux-kärna i användarutrymme (gVisor Sentry) och en nätverksstack i användarutrymme (netstack) inuti en vanlig, icke-privilegierad process.

1. Namnrymder och monteringstabell i minnet (VFS2)
När dockerd, containerd och runc körs inuti rungv fångar systrap upp deras systemanrop och dirigerar dem till den processinterna Sentry-kärnan i stället för till värdens kärna:
unshare(2),clone(2),pivot_root(2),chroot(2)ochmount(2)opererar på Sentrys uppgiftshierarki i minnet och monteringstabellenVFS2(procfs,sysfs,tmpfs,devpts,cgroupfsv2), medan värdprocessenrungvkörs under ditt icke-privilegierade värd-UID.
2. Inbyggd overlayfs på enfils-volymer av typen ext4lite
När du anger -v gvx-docker:/var/lib/docker (eller --mount type=volume,src=/disk/gvx-docker.ext4,dst=/var/lib/docker) monterar gvx sitt inbyggda filsystem ext4lite på /var/lib/docker.
Eftersom ext4lite implementerar ett JBD2-journalfört ext4-filsystem inuti en enda värdfil (gvx-docker.ext4) med stöd för trusted.overlay.*-utökade attribut, teckenbaserade whiteout-enheter (0:0), d_type och RENAME_EXCHANGE, använder dockerd sin inbyggda lagringsdrivrutin overlayfs inuti gästen. Flerstegs-docker build-operationer delar Copy-on-Write-lager utan /dev/fuse och utan den diskutrymmesexplosion som Dockers reservdrivrutin vfs orsakar.
3. Användarutrymmes-bryggan docker0 och iptables-legacy
När docker:dind startar inuti gvx:
- Gästens
dockerdskapar bryggandocker0(172.17.0.1/16), kopplar virtuellaveth-par för kapslade containers och programmerar kedjornaNAT(DOCKER,POSTROUTING) ochFILTERmed matchningar föraddrtypeochconntrackinutigvx:snetstacki användarutrymme. - Med
-p unix:~/.gvx/docker.sock:2375binds ett värdbaserat Unix-domänsocket (läge0600), och anslutningar vidarebefordras direkt till port2375pådockerdinuti sandlådan.
Jämförelse med befintliga containerverktyg
| Förmåga / begränsning | Standard-Docker (dockerd) | Rootless Docker / Podman | Kaniko / Buildah (icke-privilegierad) | gvx (rungv + docker:dind) |
|---|---|---|---|---|
Kräver värdens root eller sudo | Ja | Nej | Nej | Nej |
Fungerar med PR_SET_NO_NEW_PRIVS=1 | Nej | Nej (newuidmap misslyckas) | Delvis | Ja |
Fungerar när unshare(CLONE_NEWUSER) är blockerad (EPERM) | Ej tillämpligt | Nej | Buildah: Nej / Kaniko: Ja | Ja |
Fungerar utan /dev/fuse | Ja (använder kärnans overlay2) | Endast via långsam vfs-kopiering | Ja | Ja (overlayfs på ext4lite) |
Stöder docker build (BuildKit) | Ja | Ja (om userns tillåts) | Endast bygge av images (ingen körning) | Ja |
Stöder docker run och docker compose up | Ja | Ja (om userns tillåts) | Nej | Ja |
| Körs på Windows och macOS utan Linux-VM | Nej (kräver WSL2 / VM) | Nej (kräver Linux-VM) | Nej | Ja (whpx, hvf, systrap) |
Exakta krav på värdens kärna i Linux
gvx kräver noll förhöjda förmågor (CapEff: 0000000000000000) och noll användarnamnrymder. På en Linux-värd förlitar sig rungv endast på tre standardprimitiver i icke-privilegierad kärna:
ptrace(PTRACE_ATTACH)på sin egen underordnade tråd en gång under initieringen:systrapstartar en lokal stubbhjälptråd vid uppstart, kopplar sig till den för att initiera det delade minneskontexten och kopplar sedan loss. Om värden sätterkernel.yama.ptrace_scope = 3(vilket inaktiverar allptracesystemomfattande) eller blockerarptracei ett yttre seccomp-filter, kan initieringen avsystrapinte slutföras. (Underyama.ptrace_scope = 1, standard på Ubuntu och Debian, lyckasgvxeftersom spårning från förälder till barn är tillåten.)seccomp(SECCOMP_SET_MODE_FILTER): Används för att fånga gästens systemanrop från containerns stubbtrådar. Som beskrivs i del 3 av denna serie fungerargvxbåde närSECCOMP_FILTER_FLAG_NEW_LISTENERär tillgänglig och när det returnerarEBUSYinuti en kapslad sandlåda.mmap(..., PROT_EXEC, ...): Används för att mappa gästens ELF-segment och det delade minnets trampolin försystrap.
Exempel från start till slut: Bygga och testa en app med flera containers utan root
Följande skript kör ett komplett docker build och ett integrationstest med två containers (redis + applikationscontainer) inom en icke-privilegierad användarsession:
1mkdir -p ~/.gvx
2rungv run \
3 -p unix:~/.gvx/docker.sock:2375 \
4 -v gvx-docker:/var/lib/docker \
5 -e DOCKER_TLS_CERTDIR= \
6 docker:dind --tls=false &
7DIND_PID=$!
8
9export DOCKER_HOST="unix://$HOME/.gvx/docker.sock"
10until docker info >/dev/null 2>&1; do sleep 0.5; done
11
12mkdir -p /tmp/demo-app && cd /tmp/demo-app
13cat <<'EOF' > Dockerfile
14FROM alpine:3.20
15RUN apk add --no-cache redis
16CMD ["redis-cli", "-h", "cache", "ping"]
17EOF
18
19# Bygg imagen med overlayfs på ext4lite
20docker build -t demo-ping:latest .
21
22# Skapa ett bryggnätverk, starta Redis och verifiera anslutningen mellan containers
23docker network create demo-net
24docker run -d --name cache --network demo-net redis:7-alpine
25docker run --rm --network demo-net demo-ping:latest
26# Utdata: PONG
27
28# Rensa arbetscontainers och stoppa sandlådan
29docker rm -f cache
30docker network rm demo-net
31kill -INT $DIND_PID
Vidare läsning i denna serie
- gvx: Köra Linux-containers, Docker och Kubernetes i en enda icke-privilegierad process: Arkitekturöversikt över
gvx, dess plattformsoberoende exekveringsmotorer (whpx,hvf,systrap),VFS2(erofs,ext4lite,hostfsv2) ochnetstack. - Köra Docker, docker build och docker compose utan root eller användarnamnrymder (detta inlägg)
- Köra Docker-in-Docker inuti gVisor och kapslade sandlådor med gvx: Hur
gvxlösermodprobe,iptables-nft,overlay2pågoferoch kapsladSECCOMP_FILTER_FLAG_NEW_LISTENER(EBUSY) inutigVisor(runsc). - Snabba isolerade Docker-miljöer för RL-rollouts av AI-agenter med gvx: Skalning av parallella
SWE-bench- och RL-rollout-miljöer med återställningar av.ext4-volymer med Copy-on-Write på 100 millisekunder.