Kørsel af Docker, docker build og docker compose uden root eller user namespaces

Hurtig løsning: Sikker unprivilegeret Docker i tre trin
Hvis du arbejder i en låst Linux-container, CI-runner, Kubernetes Pod eller sandkasse til en AI-kodeagent (f.eks. et cloud-agentberegningsmiljø), hvor root, sudo, brugernavnerum (unshare(CLONE_NEWUSER)), mount(2) og /dev/fuse er blokeret, er gvx (rungv) den sikre, lavindsatsbaserede og token-effektive løsning til at køre en fuld docker:dind-motor i brugerrum.
Lavindsats- og token-effektiv løsning til AI-kodeagenter: Når en autonom kodeagent støder på
Cannot connect to the Docker daemon, spilder forsøg på at installere og patchedocker.io,podmanellerrootlesskitinde i en begrænset container typisk 15 til 30 værktøjskald og titusindvis af kontekst-tokens på at cykle gennemsystemctl-,ulimit-,iptables-,unshare- ogrunc-fejl, kun for at fejle eller falde tilbage til manuel omskrivning afDockerfileer. Medgvx(rungv) udfører agenten én deterministisk 3-trins opstart i en enkelt tur og kører straks standardkommandoernedocker build,docker runogdocker composeuændret.
Hvorfor
gvxer sikker by design (ikke en omgåelse af privilegier): I modsætning til at montere værtens/var/run/docker.sockeller køredocker run --privileged(som giver root-ækvivalent kontrol over værtskernen), omgår eller svækkergvxikke nogen sikkerhedspolitik på værten (PR_SET_NO_NEW_PRIVS,seccomp, AppArmor eller begrænsninger for ikke-root-UID). I stedet låserrungvsin egen værtsproces (PR_SET_NO_NEW_PRIVS+ en streng BPFseccomp-tilladelsesliste) og kørerdockerdinde i Googles hukommelsessikre gVisor (Sentry) brugerrumskerne. Alle gæstensUID 0-capabilities,overlayfs-monteringer (ext4lite) ogiptables-regler forbliver strengt isolerede inde i sandkasseprocessen.
1# 1. Installer rungv i brugerrum (forudbygget SLSA-attesteret release eller go install)
2# Mulighed A: Verificer og udpak den SLSA-attesterede forudbyggede binærfil 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# Mulighed 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 inde i gvx med et enkeltfil ext4lite-volumen
12# Videresender ~/.gvx/docker.sock (tilstand 0600) til gæsteport 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. Peg den standard Docker CLI og Docker Compose mod brugerrums-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# Output: overlayfs Alpine Linux ... (containeriseret)
26
27docker build -t app:test .
28docker run --rm app:test
29docker compose up -d
Hvorfor standard rootless-værktøjer fejler i begrænsede sandkasser
Når en ingeniør eller en autonom kodeagent skal køre docker build, docker run eller docker compose inde i en hærdet container eller en multi-tenant runner, fejler standardløsningerne ved fem forskellige kernebarrierer.
1. Ingen værts-Docker-daemon-socket (systemctl og service docker start fejler også)
Kørsel af docker ps eller docker build fejler straks, når værtens /var/run/docker.sock ikke er monteret i miljøet, og forsøg på at starte docker.io via systemctl eller service docker start fejler, fordi PID 1 ikke er systemd, og /etc/init.d/docker rammer containerens hårde ulimit -n-loft:
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 blokerer sudo og setuid-hjælpeprogrammer
Hærdede containere (securityContext.allowPrivilegeEscalation: false i Kubernetes, --security-opt=no-new-privileges i Docker, eller exebox- / bwrap-sandkasser) sætter Linux-bitten PR_SET_NO_NEW_PRIVS på procestræet. Forsøg på at eskalere via sudo eller setuid-binærfiler (newuidmap, newgidmap, fusermount3) fejler:
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-politikker blokerer unshare(CLONE_NEWUSER)
Værktøjer, der markedsføres som "rootless" (Rootless Docker, Podman, Buildah, nerdctl, bubblewrap), er stadig afhængige af Linux-brugernavnerum (CLONE_NEWUSER). De fejler, når:
- Den ydre containers standard-seccomp-profil blokerer
unshare(2)ellerclone(CLONE_NEWUSER). - Ubuntu 24.04+ aktiverer
kernel.apparmor_restrict_unprivileged_userns = 1. - Debian- eller RHEL-noder sætter
kernel.unprivileged_userns_clone = 0elleruser.max_user_namespaces = 0. newuidmapikke kan skrive til/proc/self/uid_map, fordiPR_SET_NO_NEW_PRIVSer aktiv.
De resulterende fejl ser således ud:
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 blokeret under docker build uden værtens CAP_SYS_ADMIN
Selv hvis et miljø tillader CLONE_NEWUSER, eller dockerd tvinges til at starte med --iptables=false --bridge=none --storage-driver=vfs, fejler docker build ved den første RUN-instruktion, fordi montering af en ny /proc eller kald af pivot_root(2) inde i et indlejret mount-namespace er blokeret:
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 ødelægger fuse-overlayfs
Rootless container-motorer, der ikke kan montere kernel-overlayfs, falder tilbage til fuse-overlayfs. I minimale containere eller Kubernetes-pods uden /dev/fuse-enhedsgennemgang fejler fuse-overlayfs straks:
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
Sådan kører gvx docker:dind helt i brugerrum
gvx omgår alle fem kernebarrierer, fordi den ikke beder værtens Linux-kerne om at oprette namespaces, montere filsystemer eller konfigurere netværksgrænseflader. I stedet kører rungv en intern Linux-kerne i brugerrum (gVisor Sentry) og en netværksstak i brugerrum (netstack) inde i én almindelig, unprivilegeret proces.

1. Namespaces og monteringstabel i hukommelsen (VFS2)
Når dockerd, containerd og runc udføres inde i rungv, opfanger systrap deres systemkald og router dem til den interne Sentry-kerne i stedet for værtskernen:
unshare(2),clone(2),pivot_root(2),chroot(2)ogmount(2)opererer på Sentry'ens opgavehierarki ogVFS2-monteringstabel i hukommelsen (procfs,sysfs,tmpfs,devpts,cgroupfsv2), mens værtsprocessenrungvkører under din unprivilegerede UID på værten.
2. Native overlayfs på ext4lite-volumener i én fil
Når du angiver -v gvx-docker:/var/lib/docker (eller --mount type=volume,src=/disk/gvx-docker.ext4,dst=/var/lib/docker), monterer gvx sit indbyggede ext4lite-filsystem på /var/lib/docker.
Da ext4lite implementerer et JBD2-journaleret ext4-filsystem inde i en enkelt værtsfil (gvx-docker.ext4) med understøttelse af trusted.overlay.*-udvidede attributter, tegn-whiteout-enheder (0:0), d_type og RENAME_EXCHANGE, bruger dockerd sin native overlayfs-lagerdriver inde i gæsten. Flertrins-docker build-operationer deler Copy-on-Write-lag uden /dev/fuse og uden den diskplads-eksplosion, som Dockers vfs-reservedriver medfører.
3. docker0-bro i brugerrum og iptables-legacy
Når docker:dind starter inde i gvx:
- Gæste-
dockerdopretterdocker0-broen (172.17.0.1/16), tilslutter virtuelleveth-par til indlejrede containere og programmererNAT- (DOCKER,POSTROUTING) ogFILTER-kæder medaddrtype- ogconntrack-match inde igvx's netstack i brugerrum. - Angivelse af
-p unix:~/.gvx/docker.sock:2375binder et Unix-domænesocket på værten (tilstand0600) og videresender forbindelser direkte til port2375fordockerdi sandkassen.
Sammenligning med eksisterende containerværktøjer
| Egenskab / Begrænsning | Standard Docker (dockerd) | Rootless Docker / Podman | Kaniko / Buildah (unprivilegeret) | gvx (rungv + docker:dind) |
|---|---|---|---|---|
Kræver værts-root eller sudo | Ja | Nej | Nej | Nej |
Virker med PR_SET_NO_NEW_PRIVS=1 | Nej | Nej (newuidmap fejler) | Delvist | Ja |
Virker når unshare(CLONE_NEWUSER) er blokeret (EPERM) | Ikke relevant | Nej | Buildah: Nej / Kaniko: Ja | Ja |
Virker uden /dev/fuse | Ja (bruger kernel-overlay2) | Kun via langsom vfs-kopiering | Ja | Ja (overlayfs på ext4lite) |
Understøtter docker build (BuildKit) | Ja | Ja (hvis userns er tilladt) | Kun image-build (ingen runtime) | Ja |
Understøtter docker run og docker compose up | Ja | Ja (hvis userns er tilladt) | Nej | Ja |
| Kører på Windows og macOS uden en Linux-VM | Nej (kræver WSL2 / VM) | Nej (kræver Linux-VM) | Nej | Ja (whpx, hvf, systrap) |
Præcise krav til værtens kernel på Linux
gvx kræver nul forhøjede capabilities (CapEff: 0000000000000000) og nul brugernavnerum. På en Linux-vært er rungv afhængig af kun tre standard unprivilegerede kerne-primitiver:
ptrace(PTRACE_ATTACH)på sin egen underordnede tråd én gang under initialisering:systrapstarter ved opstart en lokal stub-hjælpetråd, tilslutter sig den for at initialisere den delte hukommelseskontekst og frakobler sig igen. Hvis værten sætterkernel.yama.ptrace_scope = 3(som deaktiverer alptracesystemvidt) eller blokererptracei et ydre seccomp-filter, kansystrap-initialiseringen ikke gennemføres. (Underyama.ptrace_scope = 1, standarden på Ubuntu og Debian, lykkesgvx, fordi sporing fra forælder til barn er tilladt.)seccomp(SECCOMP_SET_MODE_FILTER): Bruges til at fange gæstesystemkald fra container-stub-tråde. Som beskrevet i del 3 af denne serie virkergvx, både nårSECCOMP_FILTER_FLAG_NEW_LISTENERer tilgængelig, og når den returnererEBUSYinde i en indlejret sandkasse.mmap(..., PROT_EXEC, ...): Bruges til at mappe gæste-ELF-segmenter ogsystraps trampolin til delt hukommelse.
Eksempel fra start til slut: Bygning og test af en multi-container-app uden root
Følgende script kører en komplet docker build og en integrationstest med to containere (redis + applikationscontainer) inde i en unprivilegeret brugersession:
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# Byg image'et ved hjælp af overlayfs på ext4lite
20docker build -t demo-ping:latest .
21
22# Opret et bro-netværk, start Redis, og verificer forbindelsen mellem 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# Output: PONG
27
28# Ryd op i arbejdsbelastningscontainerne og stop sandkassen
29docker rm -f cache
30docker network rm demo-net
31kill -INT $DIND_PID
Yderligere læsning i denne serie
- gvx: Kørsel af Linux-containere, Docker og Kubernetes i én unprivilegeret proces: Arkitekturoversigt over
gvx, dets tværplatforms eksekveringsmotorer (whpx,hvf,systrap),VFS2(erofs,ext4lite,hostfsv2) ognetstack. - Kørsel af Docker, docker build og docker compose uden root eller brugernavnerum (dette indlæg)
- Kørsel af Docker-in-Docker inde i gVisor og indlejrede sandkasser med gvx: Hvordan
gvxløsermodprobe,iptables-nft,overlay2pågoferog indlejretSECCOMP_FILTER_FLAG_NEW_LISTENER(EBUSY) inde igVisor(runsc). - Hurtige isolerede Docker-miljøer til AI-agenters RL-rollouts med gvx: Skalering af parallelle
SWE-bench- og RL-rollout-miljøer med copy-on-write.ext4-volumen-nulstillinger på 100 millisekunder.