Spúšťanie Docker, docker build a docker compose bez root oprávnení alebo používateľských menných priestorov

Rýchle riešenie: Bezpečný neprivilegovaný Docker v troch krokoch
Ak pracujete vo vnútri uzamknutého Linux kontajnera, CI runnera, Kubernetes Podu alebo pieskoviska AI kódovacieho agenta (napríklad výpočtového prostredia cloudového agenta), kde sú blokované root, sudo, používateľské menné priestory (unshare(CLONE_NEWUSER)), mount(2) a /dev/fuse, je gvx (rungv) bezpečným, nenáročným a úsporným na tokeny riešením na spustenie plného enginu docker:dind v používateľskom priestore.
Riešenie s nízkou námahou a úsporou tokenov pre AI kódovacích agentov: Keď autonómny kódovací agent narazí na chybu
Cannot connect to the Docker daemon, pokus o inštaláciu a záplatovaniedocker.io,podmanaleborootlesskitvo vnútri obmedzeného kontajnera typicky spotrebuje 15 až 30 volaní nástrojov a desiatky tisíc kontextových tokenov pri cyklení cez chybysystemctl,ulimit,iptables,unsharearunc, pričom výsledkom je zlyhanie alebo návrat k manuálnemu prepisovaniu súborovDockerfile. Sgvx(rungv) agent vykoná jeden deterministický trojkrokový bootstrap v jedinom kroku a okamžite spustí štandardné príkazydocker build,docker runadocker composebez zmeny.
Prečo je
gvxbezpečný už z návrhu (nie obchádzka eskalácie oprávnení): Na rozdiel od pripojenia hostiteľského/var/run/docker.sockalebo spusteniadocker run --privileged(ktoré poskytujú kontrolu ekvivalentnú roote nad jadrom hostiteľa)gvxneobchádza ani neoslabuje žiadnu bezpečnostnú politiku hostiteľa (PR_SET_NO_NEW_PRIVS,seccomp, AppArmor ani obmedzenia neroot UID). Namiesto tohorungvuzamkne svoj vlastný hostiteľský proces (PR_SET_NO_NEW_PRIVS+ prísny zoznam povolených BPFseccomp) a spustídockerdvo vnútri používateľského jadra gVisor (Sentry) od Googlu, ktoré je bezpečné z hľadiska pamäte. Všetky schopnostiUID 0hosťa, pripojeniaoverlayfs(ext4lite) a pravidláiptableszostávajú prísne izolované vo vnútri procesu pieskoviska.
1# 1. Inštalácia rungv v používateľskom priestore (predkompilované vydanie overené SLSA alebo go install)
2# Možnosť A: Overenie a extrakcia predkompilovaného binárneho súboru overeného SLSA z 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# Možnosť B: Alebo inštalácia priamo zo zdrojového kódu pomocou Go
9CGO_ENABLED=0 GOBIN=~/.local/bin go install z.gfire.dev/gvx/cmd/rungv@latest
10
11# 2. Spustenie docker:dind vo vnútri gvx so zväzkom ext4lite v jedinom súbore
12# Presmerováva ~/.gvx/docker.sock (režim 0600) na port 2375 hosťa
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. Nasmerovanie štandardného Docker CLI a Docker Compose na socket v používateľskom priestore
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# Výstup: overlayfs Alpine Linux ... (kontajnerizované)
26
27docker build -t app:test .
28docker run --rm app:test
29docker compose up -d
Prečo štandardné nástroje bez roota zlyhávajú v obmedzených pieskoviskách
Keď inžinier alebo autonómny kódovací agent potrebuje spustiť docker build, docker run alebo docker compose vo vnútri vytvrdeného kontajnera alebo viacnájomcového runnera, štandardné obchádzky zlyhajú na piatich odlišných bariérach jadra.
1. Chýbajúci socket démona Docker hostiteľa (zlyhávajú aj systemctl a service docker start)
Spustenie docker ps alebo docker build zlyhá okamžite, keď hostiteľský /var/run/docker.sock nie je pripojený do prostredia, a pokus o spustenie docker.io cez systemctl alebo service docker start zlyhá, pretože PID 1 nie je systemd a /etc/init.d/docker narazí na pevný limit ulimit -n kontajnera:
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 blokuje sudo a pomocné programy setuid
Vytvrdené kontajnery (securityContext.allowPrivilegeEscalation: false v Kubernetes, --security-opt=no-new-privileges v Dockeri alebo pieskoviská exebox / bwrap) nastavujú bit Linuxu PR_SET_NO_NEW_PRIVS na strome procesov. Pokus o eskaláciu cez sudo alebo binárne súbory setuid (newuidmap, newgidmap, fusermount3) zlyhá:
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. Politiky seccomp a sysctl blokujú unshare(CLONE_NEWUSER)
Nástroje propagované ako „rootless“ (Rootless Docker, Podman, Buildah, nerdctl, bubblewrap) sa stále spoliehajú na používateľské menné priestory Linuxu (CLONE_NEWUSER). Zlyhávajú vždy, keď:
- Predvolený profil seccomp vonkajšieho kontajnera blokuje
unshare(2)aleboclone(CLONE_NEWUSER). - Ubuntu 24.04+ povolí
kernel.apparmor_restrict_unprivileged_userns = 1. - Uzly Debian alebo RHEL nastavia
kernel.unprivileged_userns_clone = 0alebouser.max_user_namespaces = 0. newuidmapnemôže zapisovať do/proc/self/uid_map, pretože je aktívnyPR_SET_NO_NEW_PRIVS.
Výsledné chyby vyzerajú takto:
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) a pivot_root(2) sú blokované počas docker build bez CAP_SYS_ADMIN hostiteľa
Aj keď prostredie povoľuje CLONE_NEWUSER alebo sa dockerd vynúti spustiť s --iptables=false --bridge=none --storage-driver=vfs, spustenie docker build zlyhá pri prvej inštrukcii RUN, pretože pripojenie nového /proc alebo volanie pivot_root(2) vo vnorenom mount namespace je blokované:
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. Chýbajúci /dev/fuse narúša fuse-overlayfs
Kontajnerové enginy bez roota, ktoré nedokážu pripojiť jadrový overlayfs, sa prepnú na fuse-overlayfs. V minimalistických kontajneroch alebo Kubernetes podoch bez preposlania zariadenia /dev/fuse fuse-overlayfs okamžite zlyhá:
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
Ako gvx spúšťa docker:dind úplne v používateľskom priestore
gvx obchádza všetkých päť bariér jadra, pretože nežiada hostiteľské jadro Linuxu o vytváranie menných priestorov, pripájanie súborových systémov ani konfiguráciu sieťových rozhraní. Namiesto toho rungv spúšťa interné jadro Linuxu v používateľskom priestore (gVisor Sentry) a sieťový zásobník v používateľskom priestore (netstack) v rámci jedného bežného neprivilegovaného procesu.

1. Menné priestory a tabuľka pripojení v pamäti (VFS2)
Keď dockerd, containerd a runc bežia vo vnútri rungv, systrap zachytáva ich systémové volania a smeruje ich do procesového jadra Sentry namiesto jadra hostiteľa:
unshare(2),clone(2),pivot_root(2),chroot(2)amount(2)pracujú nad hierarchiou úloh Sentry v pamäti a tabuľkou pripojeníVFS2(procfs,sysfs,tmpfs,devpts,cgroupfsv2), zatiaľ čo hostiteľský procesrungvbeží pod vaším neprivilegovaným UID hostiteľa.
2. Natívny overlayfs na zväzkoch ext4lite v jedinom súbore
Keď odovzdáte -v gvx-docker:/var/lib/docker (alebo --mount type=volume,src=/disk/gvx-docker.ext4,dst=/var/lib/docker), gvx pripojí svoj vstavaný súborový systém ext4lite na /var/lib/docker.
Keďže ext4lite implementuje súborový systém ext4 s žurnálom JBD2 vo vnútri jedného hostiteľského súboru (gvx-docker.ext4) s podporou rozšírených atribútov trusted.overlay.*, znakových whiteout zariadení (0:0), d_type a RENAME_EXCHANGE, dockerd používa svoj natívny ovládač úložiska overlayfs vo vnútri hosťa. Viacstupňové operácie docker build zdieľajú vrstvy Copy-on-Write bez /dev/fuse a bez nárastu využitia diskového priestoru, ktorý spôsobuje záložný ovládač vfs v Dockeri.
3. Most docker0 v používateľskom priestore a iptables-legacy
Keď sa docker:dind spustí vo vnútri gvx:
dockerdhosťa vytvorí mostdocker0(172.17.0.1/16), pripojí virtuálne páryvethpre vnorené kontajnery a naprogramuje reťazceNAT(DOCKER,POSTROUTING) aFILTERso zhodamiaddrtypeaconntrackvo vnútri používateľskéhonetstacksystémugvx.- Odovzdanie
-p unix:~/.gvx/docker.sock:2375viaže hostiteľský socket Unix domény (režim0600) a presmerováva pripojenia priamo na port2375dockerdvo vnútri pieskoviska.
Porovnanie s existujúcimi nástrojmi pre kontajnery
| Schopnosť / obmedzenie | Štandardný Docker (dockerd) | Rootless Docker / Podman | Kaniko / Buildah (neprivilegovaný) | gvx (rungv + docker:dind) |
|---|---|---|---|---|
Vyžaduje sa root alebo sudo hostiteľa | Áno | Nie | Nie | Nie |
Funguje s PR_SET_NO_NEW_PRIVS=1 | Nie | Nie (newuidmap zlyhá) | Čiastočne | Áno |
Funguje, keď je unshare(CLONE_NEWUSER) blokované (EPERM) | N/A | Nie | Buildah: Nie / Kaniko: Áno | Áno |
Funguje bez /dev/fuse | Áno (používa jadrový overlay2) | Iba cez pomalú kópiu vfs | Áno | Áno (overlayfs na ext4lite) |
Podporuje docker build (BuildKit) | Áno | Áno (ak je povolený userns) | Iba zostavenie obrazu (bez runtime) | Áno |
Podporuje docker run a docker compose up | Áno | Áno (ak je povolený userns) | Nie | Áno |
| Beží na Windows a macOS bez VM Linuxu | Nie (vyžaduje WSL2 / VM) | Nie (vyžaduje VM Linuxu) | Nie | Áno (whpx, hvf, systrap) |
Presné požiadavky na jadro hostiteľa Linux
gvx nevyžaduje žiadne zvýšené schopnosti (CapEff: 0000000000000000) a žiadne používateľské menné priestory. Na hostiteľovi Linuxu sa rungv spolieha iba na tri štandardné neprivilegované primitíva jadra:
ptrace(PTRACE_ATTACH)na jeho vlastnom podriadenom vlákne jednorazovo počas inicializácie:systrappri štarte vytvorí pomocné vlákno stub, pripojí sa k nemu na inicializáciu zdieľaného kontextu pamäte a odpojí sa. Ak hostiteľ nastavíkernel.yama.ptrace_scope = 3(čím sa zakážu všetkyptracev celom systéme) alebo blokujeptracevo vonkajšom filtri seccomp, inicializáciasystrapsa nemôže dokončiť. (Priyama.ptrace_scope = 1, predvolenom nastavení na Ubuntu a Debiane,gvxuspeje, pretože sledovanie z rodiča na potomka je povolené.)seccomp(SECCOMP_SET_MODE_FILTER): Slúži na zachytávanie systémových volaní hosťa z pomocných vlákien stub kontajnera. Ako je uvedené v 3. časti tohto seriálu,gvxfunguje tak, keď jeSECCOMP_FILTER_FLAG_NEW_LISTENERdostupný, ako aj vtedy, keď vo vnorenom pieskovisku vrátiEBUSY.mmap(..., PROT_EXEC, ...): Slúži na mapovanie segmentov ELF hosťa a trampolínysystrapso zdieľanou pamäťou.
Komplexný príklad: zostavenie a testovanie viackontajnerovej aplikácie bez roota
Nasledujúci skript spustí kompletné docker build a integračný test s dvoma kontajnermi (redis + kontajner aplikácie) v neprivilegovanej používateľskej relácii:
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# Zostavenie obrazu pomocou overlayfs na ext4lite
20docker build -t demo-ping:latest .
21
22# Vytvorenie mostovej siete, spustenie Redis a overenie konektivity medzi kontajnermi
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# Výstup: PONG
27
28# Vyčistenie pracovných kontajnerov a zastavenie pieskoviska
29docker rm -f cache
30docker network rm demo-net
31kill -INT $DIND_PID
Ďalšie čítanie v tomto seriáli
- gvx: Spúšťanie kontajnerov Linux, Docker a Kubernetes v jednom neprivilegovanom procese: Architektonický prehľad
gvx, jeho multiplatformných výpočtových enginov (whpx,hvf,systrap),VFS2(erofs,ext4lite,hostfsv2) anetstack. - Spúšťanie Docker, docker build a docker compose bez roota a používateľských menných priestorov (tento príspevok)
- Spúšťanie Docker-in-Docker vo vnútri gVisor a vnorených pieskovísk pomocou gvx: Ako
gvxriešimodprobe,iptables-nft,overlay2nagofera vnorenýSECCOMP_FILTER_FLAG_NEW_LISTENER(EBUSY) vo vnútrigVisor(runsc). - Rýchle izolované Docker prostredia pre RL rollouty AI agentov pomocou gvx: Škálovanie paralelných prostredí
SWE-bencha RL rolloutov pomocou resetov zväzkov.ext4typu copy-on-write v trvaní 100 milisekúnd.