Kjøre Docker, docker build og docker compose uten root eller brukernavnrom

Rask løsning: Sikker unprivilegert Docker i tre trinn
Hvis du arbeider i en låst Linux-container, CI-runner, Kubernetes Pod eller et sandkassemiljø for AI-kodeagenter (for eksempel et compute-miljø for skyagenter) der root, sudo, brukernavnrom (unshare(CLONE_NEWUSER)), mount(2) og /dev/fuse er blokkert, er gvx (rungv) den sikre, lavinnsats- og tokeneffektive løsningen for å kjøre en fullstendig docker:dind-motor i brukerrom.
Lavinnsats- og tokeneffektiv løsning for AI-kodeagenter: Når en autonom kodeagent får
Cannot connect to the Docker daemon, vil forsøk på å installere og patchedocker.io,podmanellerrootlesskiti en begrenset container typisk kaste bort 15 til 30 verktøykall-runder og titusenvis av kontekst-tokens på å sykle gjennom feil frasystemctl,ulimit,iptables,unshareogrunc, bare for å mislykkes eller falle tilbake til manuell omskriving avDockerfile-filer. Medgvx(rungv) kjører agenten én deterministisk 3-trinns oppstart i en enkelt runde og kjører deretter umiddelbart standarddocker build,docker runogdocker compose-kommandoer uendret.
Hvorfor
gvxer trygt by design (ikke en omgåelse av privilegieeskalering): I motsetning til å montere vertens/var/run/docker.sockeller kjøredocker run --privileged(som gir rotekvivalent kontroll over vertskjernen), omgår eller svekker ikkegvxnoen sikkerhetspolicy på verten (PR_SET_NO_NEW_PRIVS,seccomp, AppArmor eller begrensninger for ikke-root-UID). I stedet låserrungvsin egen vertsprosess (PR_SET_NO_NEW_PRIVS+ streng BPFseccomp-tillatelsesliste) og kjørerdockerdinne i Googles minnesikre gVisor (Sentry) brukerrom-kjerne. Alle gjestensUID 0-egenskaper,overlayfs-montasjer (ext4lite) ogiptables-regler forblir strengt isolert inne i sandkasseprosessen.
1# 1. Installer rungv i brukerrom (forhåndsbygd SLSA-attestert utgivelse eller go install)
2# Alternativ A: Verifiser og pakk ut den SLSA-attesterte forhåndsbygde binærfilen fra 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 installer direkte fra kildekode med Go
9CGO_ENABLED=0 GOBIN=~/.local/bin go install z.gfire.dev/gvx/cmd/rungv@latest
10
11# 2. Start docker:dind inne i gvx med et enkelt ext4lite-volum (én fil)
12# Videresender ~/.gvx/docker.sock (modus 0600) til gjestens 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. Pek standard Docker-CLI og Docker Compose mot brukerrom-socketen
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
Hvorfor standard rootless-verktøy feiler i begrensede sandkasser
Når en ingeniør eller autonom kodeagent trenger å kjøre docker build, docker run eller docker compose inne i en herdet container eller multi-tenant runner, feiler standard omgåelser ved fem distinkte kjernebarrierer.
1. Ingen vert-Docker-daemon-socket (systemctl og service docker start feiler også)
Kjøring av docker ps eller docker build feiler umiddelbart når vertens /var/run/docker.sock ikke er montert inn i miljøet, og forsøk på å starte docker.io via systemctl eller service docker start feiler fordi PID 1 ikke er systemd, og /etc/init.d/docker treffer containerens harde 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 blokkerer sudo og setuid-hjelpeprogrammer
Herdede containere (securityContext.allowPrivilegeEscalation: false i Kubernetes, --security-opt=no-new-privileges i Docker, eller exebox- / bwrap-sandkasser) setter Linux-biten PR_SET_NO_NEW_PRIVS på prosesstreet. Forsøk på å eskalere via sudo eller setuid-binærfiler (newuidmap, newgidmap, fusermount3) feiler:
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- og sysctl-policyer blokkerer unshare(CLONE_NEWUSER)
Verktøy markedsført som "rootless" (Rootless Docker, Podman, Buildah, nerdctl, bubblewrap) er fortsatt avhengige av Linux-brukernavnrom (CLONE_NEWUSER). De feiler når:
- Den ytre containerens standard seccomp-profil blokkerer
unshare(2)ellerclone(CLONE_NEWUSER). - Ubuntu 24.04+ aktiverer
kernel.apparmor_restrict_unprivileged_userns = 1. - Debian- eller RHEL-noder setter
kernel.unprivileged_userns_clone = 0elleruser.max_user_namespaces = 0. newuidmapikke kan skrive til/proc/self/uid_mapfordiPR_SET_NO_NEW_PRIVSer aktiv.
De resulterende feilene ser slik ut:
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) og pivot_root(2) er blokkert under docker build uten vertens CAP_SYS_ADMIN
Selv om et miljø tillater CLONE_NEWUSER, eller dockerd tvinges til å starte med --iptables=false --bridge=none --storage-driver=vfs, feiler docker build ved den første RUN-instruksjonen, fordi montering av en ny /proc eller kall til pivot_root(2) inne i et nøstet monteringsnavnerom er blokkert:
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. Manglende /dev/fuse ødelegger fuse-overlayfs
Rootless container-motorer som ikke kan montere kjerne-overlayfs, faller tilbake til fuse-overlayfs. I minimale containere eller Kubernetes-pods uten videreføring av enheten /dev/fuse feiler fuse-overlayfs umiddelbart:
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
Hvordan gvx kjører docker:dind helt i brukerrom
gvx omgår alle fem kjernebarrierene fordi den ikke ber vertens Linux-kjerne om å opprette navnerom, montere filsystemer eller konfigurere nettverksgrensesnitt. I stedet kjører rungv en intern Linux-kjerne i brukerrom (gVisor Sentry) og en nettverksstakk i brukerrom (netstack) inne i én vanlig uprivilegert prosess.

1. Navnerom og monteringstabell i minnet (VFS2)
Når dockerd, containerd og runc kjører inne i rungv, avskjærer systrap deres systemkall og sender dem til den prosessinterne Sentry-kjernen i stedet for vertskjernen:
unshare(2),clone(2),pivot_root(2),chroot(2)ogmount(2)opererer på Sentrys oppgavehierarki i minnet ogVFS2-monteringstabellen (procfs,sysfs,tmpfs,devpts,cgroupfsv2), mens vertsprosessenrungvkjører under din uprivilegerte vert-UID.
2. Innebygd overlayfs på ext4lite-volum i én fil
Når du sender -v gvx-docker:/var/lib/docker (eller --mount type=volume,src=/disk/gvx-docker.ext4,dst=/var/lib/docker), monterer gvx sitt innebygde ext4lite-filsystem på /var/lib/docker.
Fordi ext4lite implementerer et JBD2-journalført ext4-filsystem inne i én vertsfil (gvx-docker.ext4) med støtte for trusted.overlay.*-utvidede attributter, tegn-whiteout-enheter (0:0), d_type og RENAME_EXCHANGE, bruker dockerd sin innebygde overlayfs-lagringsdriver inne i gjesten. Flertrinns docker build-operasjoner deler Copy-on-Write-lag uten /dev/fuse og uten diskplass-eksplosjonen som følger med Dockers vfs-reservedriver.
3. Brukerrom-docker0-bro og iptables-legacy
Når docker:dind starter inne i gvx:
- Gjest-
dockerdoppretterdocker0-broen (172.17.0.1/16), kobler virtuelleveth-par for nøstede containere og programmererNAT- (DOCKER,POSTROUTING) ogFILTER-kjeder medaddrtype- ogconntrack-treff inne igvxsin brukerrom-netstack. - Ved å sende
-p unix:~/.gvx/docker.sock:2375binder man et vert-Unix-domenesocket (modus0600) og videresender tilkoblinger direkte til port2375pådockerdinne i sandkassen.
Sammenligning med eksisterende container-verktøy
| Evne / Begrensning | Standard Docker (dockerd) | Rootless Docker / Podman | Kaniko / Buildah (unprivilegert) | gvx (rungv + docker:dind) |
|---|---|---|---|---|
Krever vert root eller sudo | Ja | Nei | Nei | Nei |
Fungerer med PR_SET_NO_NEW_PRIVS=1 | Nei | Nei (newuidmap feiler) | Delvis | Ja |
Fungerer når unshare(CLONE_NEWUSER) er blokkert (EPERM) | Ikke relevant | Nei | Buildah: Nei / Kaniko: Ja | Ja |
Fungerer uten /dev/fuse | Ja (bruker kjerne-overlay2) | Kun via treg vfs-kopiering | Ja | Ja (overlayfs på ext4lite) |
Støtter docker build (BuildKit) | Ja | Ja (hvis userns er tillatt) | Kun bygging av images (ingen kjøretid) | Ja |
Støtter docker run og docker compose up | Ja | Ja (hvis userns er tillatt) | Nei | Ja |
| Kjører på Windows og macOS uten Linux-VM | Nei (krever WSL2 / VM) | Nei (krever Linux-VM) | Nei | Ja (whpx, hvf, systrap) |
Nøyaktige krav til vertskjernen på Linux
gvx krever null forhøyede egenskaper (CapEff: 0000000000000000) og null brukernavnrom. På en Linux-vert er rungv avhengig av kun tre standard uprivilegerte kjerne-primitiver:
ptrace(PTRACE_ATTACH)på sin egen barnetråd én gang under initialisering:systrapstarter en lokal stub-hjelpertråd ved oppstart, kobler seg til den for å initialisere den delte minnekonteksten og kobler fra. Hvis verten setterkernel.yama.ptrace_scope = 3(som deaktiverer allptracesystemomfattende) eller blokkererptracei et ytre seccomp-filter, kan ikkesystrap-initialiseringen fullføres. (Underyama.ptrace_scope = 1, standard på Ubuntu og Debian, lykkesgvx, fordi sporing fra forelder til barn er tillatt.)seccomp(SECCOMP_SET_MODE_FILTER): Brukes til å fange gjestens systemkall fra containerens stub-tråder. Som dekket i del 3 av denne serien, fungerergvxbåde nårSECCOMP_FILTER_FLAG_NEW_LISTENERer tilgjengelig, og når det returnererEBUSYinne i et nøstet sandkassemiljø.mmap(..., PROT_EXEC, ...): Brukes til å mappe gjestens ELF-segmenter ogsystrapsin delte minne-trampoline.
Ende-til-ende-eksempel: Bygge og teste en flerkontainer-app uten root
Følgende skript kjører en komplett docker build og en integrasjonstest med to containere (redis + applikasjonscontainer) inne i en uprivilegert brukerøkt:
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 imaget med overlayfs på ext4lite
20docker build -t demo-ping:latest .
21
22# Opprett et bro-nettverk, start Redis og verifiser tilkobling mellom containerne
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# Rydd opp i arbeidscontainerne og stopp sandkassen
29docker rm -f cache
30docker network rm demo-net
31kill -INT $DIND_PID
Videre lesning i denne serien
- gvx: Kjøre Linux-containere, Docker og Kubernetes i én unprivilegert prosess: Arkitekturoversikt over
gvx, dens plattformuavhengige kjøremotorer (whpx,hvf,systrap),VFS2(erofs,ext4lite,hostfsv2) ognetstack. - Kjøre Docker, docker build og docker compose uten root eller brukernavnrom (dette innlegget)
- Kjøre Docker-in-Docker inne i gVisor og nøstede sandkasser med gvx: Hvordan
gvxløsermodprobe,iptables-nft,overlay2pågoferog nøstetSECCOMP_FILTER_FLAG_NEW_LISTENER(EBUSY) inne igVisor(runsc). - Raske isolerte Docker-miljøer for RL-utrulling av AI-agenter med gvx: Skalering av parallelle
SWE-bench- og RL-utrullingsmiljøer med tilbakestillinger av.ext4-volumer med copy-on-write på 100 millisekunder.