Kørsel af Docker, docker build og docker compose uden root eller brugernavneområder

Hurtig løsning: Sikker unprivilegeret Docker i tre trin
Hvis du arbejder i en låst Linux-container, CI-runner, Kubernetes Pod eller AI-agent-sandbox, hvor root, sudo, brugernamespaces (unshare(CLONE_NEWUSER)), mount(2) og /dev/fuse er blokeret, er gvx (rungv) den sikre løsning med dyb forsvarsopbygning til at køre en fuld docker:dind-motor i brugerrum.
Hvorfor
gvxer sikker by design (ikke en omgåelse af privilegieeskalering): I modsætning til at montere den værts-/var/run/docker.sockeller køredocker run --privileged(som giver root-tilsvarende 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+ streng BPFseccomp-tilladelsesliste) og kørerdockerdinde i Googles hukommelsessikre gVisor (Sentry) brugerrumskerne. Alle gæst-UID 0-kapaciteter,overlayfs-monteringer (ext4lite) ogiptables-regler forbliver strengt isoleret inde i sandbox-processen.
1# 1. Installer rungv i brugerrum (forudbygget SLSA-attesteret udgivelse eller go install)
2# Mulighed A: Verificer og udpak den SLSA-attesterede forudbyggede binær 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æ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. Peg den standard Docker CLI og Docker Compose på brugerrums-socket'en
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 sandboxes
Når en ingeniør eller en autonom kodningsagent skal køre docker build, docker run eller docker compose inde i en hærdet container eller et multi-tenant runner-miljø, fejler standardløsninger ved fem særskilte kernelbarrierer.
1. Ingen værts-Docker-daemon-socket
Kørsel af docker ps eller docker build fejler straks, når værtens /var/run/docker.sock ikke er monteret i miljøet:
1Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
2. PR_SET_NO_NEW_PRIVS blokerer sudo og setuid-hjælpere
Hærdede containere (securityContext.allowPrivilegeEscalation: false i Kubernetes, --security-opt=no-new-privileges i Docker, eller exebox- / bwrap-sandboxes) sætter Linux-bitten PR_SET_NO_NEW_PRIVS på procestræet. Forsøg på at eskalere via sudo eller setuid-binære filer (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 brugernamespaces (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. newuidmapkan ikke skrive til/proc/self/uid_map, fordiPR_SET_NO_NEW_PRIVSer aktiv.
De resulterende fejl ser sådan 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) er blokeret uden værtens CAP_SYS_ADMIN
Selvom et miljø tillader CLONE_NEWUSER, fejler montering af en frisk /proc inde i et indlejret mount-namespace, hvis den ydre container har maskeret /proc-undertræer (/proc/acpi, /proc/kcore, /proc/keys) eller fjernet mount(2) i seccomp:
1mount("/proc", "/proc", "proc", MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL): Operation not permitted
2OCI 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
3bwrap: Creating new namespace failed: Operation not permitted
5. Manglende /dev/fuse ødelægger fuse-overlayfs
Rootless container-motorer, der ikke kan montere kernens overlayfs, falder tilbage til fuse-overlayfs. I minimale containere eller Kubernetes-pods uden videreførelse af /dev/fuse-enheden 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 kernelbarrierer, 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 sender dem til den in-process Sentry-kerne i stedet for værtskernen:
unshare(2),clone(2),pivot_root(2),chroot(2)ogmount(2)opererer på Sentry'ens opgavehierarki i hukommelsen ogVFS2-monteringstabellen (procfs,sysfs,tmpfs,devpts,cgroupfsv2), mens værtsprocessenrungvkører under din unprivilegerede værts-UID.
2. Indbygget overlayfs på enkeltfils-ext4lite-volumener
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-journaliseret 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 indbyggede overlayfs-lagringsdriver inde i gæsten. Flertrins docker build-operationer deler Copy-on-Write-lag uden /dev/fuse og uden den diskplads-eksplosion, som Dockers vfs-fallback-driver medfører.
3. docker0-bro i brugerrum og iptables-legacy
Når docker:dind starter inde i gvx:
- Gæst-
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'snetstacki brugerrum. - Angivelse af
-p unix:~/.gvx/docker.sock:2375binder et Unix-domænesocket på værten (tilstand0600) og videresender forbindelser direkte til port2375pådockerdinde i sandboxen.
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) | Delvis | Ja |
Virker når unshare(CLONE_NEWUSER) er blokeret (EPERM) | Ikke relevant | Nej | Buildah: Nej / Kaniko: Ja | Ja |
Virker uden /dev/fuse | Ja (bruger kernens 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ærtskernen på Linux
gvx kræver ingen forhøjede kapabiliteter (CapEff: 0000000000000000) og ingen brugernamespaces. På en Linux-vært er rungv afhængig af kun tre standard unprivilegerede kernelprimitiver:
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 afkobler 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 opfange gæstens systemkald fra containerens stub-tråde. Som beskrevet i del 3 af denne serie virkergvxbåde nårSECCOMP_FILTER_FLAG_NEW_LISTENERer tilgængelig, og når den returnererEBUSYinde i en indlejret sandbox.mmap(..., PROT_EXEC, ...): Bruges til at mappe gæstens ELF-segmenter ogsystraps delte hukommelses-trampolin.
End-to-end-eksempel: Build og test af en app med flere containere 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 imaget 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 sandboxen
29docker rm -f cache
30docker network rm demo-net
31kill -INT $DIND_PID
Yderligere læsning i denne serie
- gvx: Kør Linux-containere, Docker og Kubernetes i én unprivilegeret proces: Arkitekturoversigt over
gvx, dens tværplatforms eksekveringsmotorer (whpx,hvf,systrap),VFS2(erofs,ext4lite,hostfsv2) ognetstack. - Kør Docker, docker build og docker compose uden root eller brugernamespaces (dette indlæg)
- Kør Docker-in-Docker inde i gVisor og indlejrede sandboxes med gvx: Hvordan
gvxløsermodprobe,iptables-nft,overlay2pågoferog indlejretSECCOMP_FILTER_FLAG_NEW_LISTENER(EBUSY) inde igVisor(runsc). - Hurtige isolerede Docker-miljøer til RL-udrulninger af AI-agenter med gvx: Skalering af parallelle
SWE-bench- og RL-udrulningsmiljøer med copy-on-write.ext4-volumen-nulstillinger på 100 millisekunder.