GoSuda

Docker, docker build és docker compose futtatása root jogosultság és felhasználói névterek nélkül

By Lemon Mint views ...

Gyors megoldás: biztonságos, jogosultság nélküli Docker három lépésben

Ha egy korlátozott Linux-konténerben, CI-futtatóban, Kubernetes Podban vagy AI-ügynök homokozóban dolgozik, ahol a root, a sudo, a felhasználói névterek (unshare(CLONE_NEWUSER)), a mount(2) és a /dev/fuse le van tiltva, akkor a gvx (rungv) a biztonságos, mélyvédelmi megoldás egy teljes docker:dind motor felhasználói térben történő futtatásához.

Miért biztonságos a gvx a tervezésénél fogva (nem jogosultság-emelési megkerülés): Ellentétben a host /var/run/docker.sock csatlakoztatásával vagy a docker run --privileged használatával (amelyek root-egyenértékű irányítást biztosítanak a host kernel felett), a gvx nem kerüli meg és nem gyengíti egyik host biztonsági szabályzatot sem (PR_SET_NO_NEW_PRIVS, seccomp, AppArmor vagy a nem-root UID korlátozások). Ehelyett a rungv lezárja a saját host folyamatát (PR_SET_NO_NEW_PRIVS + szigorú BPF seccomp engedélyezőlista), és a dockerd folyamatot a Google memóriabiztos gVisor (Sentry) felhasználói térbeli kernelében futtatja. A vendég UID 0 képességei, az overlayfs csatlakoztatások (ext4lite) és az iptables szabályok szigorúan a homokozó folyamaton belül maradnak elszigetelve.

 1# 1. Az rungv telepítése felhasználói térbe (SLSA-tanúsított előre fordított kiadás vagy go install)
 2# A lehetőség: A SLSA-tanúsított, előre fordított bináris ellenőrzése és kicsomagolása a GitHub Releases oldalról
 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# B lehetőség: Vagy közvetlen telepítés forráskódból Go-val
 9CGO_ENABLED=0 GOBIN=~/.local/bin go install z.gfire.dev/gvx/cmd/rungv@latest
10
11# 2. A docker:dind indítása a gvx-en belül egyfájlos ext4lite kötettel
12#    Továbbítja a ~/.gvx/docker.sock fájlt (0600 mód) a vendég 2375-ös portjára
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. A szokásos Docker CLI és Docker Compose irányítása a felhasználói térbeli socketre
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# Kimenet: overlayfs Alpine Linux ... (containerized)
26
27docker build -t app:test .
28docker run --rm app:test
29docker compose up -d

Miért nem működnek a szokásos rootless eszközök korlátozott homokozókban

Amikor egy mérnöknek vagy egy autonóm kódoló ügynöknek egy megerősített konténerben vagy többbérlős futtatóban kell docker build, docker run vagy docker compose parancsot futtatnia, a szokásos megkerülő megoldások öt különálló kernel-akadálynál meghiúsulnak.

1. Nincs host Docker démon socket

A docker ps vagy a docker build azonnal meghiúsul, ha a host /var/run/docker.sock nincs csatlakoztatva a környezetbe:

1Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

2. A PR_SET_NO_NEW_PRIVS blokkolja a sudo-t és a setuid segédprogramokat

A megerősített konténerek (securityContext.allowPrivilegeEscalation: false Kubernetesben, --security-opt=no-new-privileges Dockerben, vagy exebox / bwrap homokozók) beállítják a Linux PR_SET_NO_NEW_PRIVS bitet a folyamatfán. A jogosultság-emelés sudo vagy setuid bináris fájlokon keresztül (newuidmap, newgidmap, fusermount3) meghiúsul:

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. A seccomp és a sysctl szabályzatok blokkolják az unshare(CLONE_NEWUSER) hívást

A „rootless” eszközök (Rootless Docker, Podman, Buildah, nerdctl, bubblewrap) továbbra is a Linux felhasználói névterekre (CLONE_NEWUSER) támaszkodnak. Meghiúsulnak, amikor:

  • A külső konténer alapértelmezett seccomp profilja blokkolja az unshare(2) vagy a clone(CLONE_NEWUSER) hívást.
  • Az Ubuntu 24.04+ verzión engedélyezve van a kernel.apparmor_restrict_unprivileged_userns = 1 beállítás.
  • A Debian vagy RHEL csomópontokon a kernel.unprivileged_userns_clone = 0 vagy a user.max_user_namespaces = 0 van beállítva.
  • A newuidmap nem tud írni a /proc/self/uid_map fájlba, mert a PR_SET_NO_NEW_PRIVS aktív.

A kapott hibaüzenetek így néznek ki:

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. A mount(2) tiltott host CAP_SYS_ADMIN nélkül

Még ha a környezet engedélyezi is a CLONE_NEWUSER használatát, egy új /proc csatlakoztatása egy beágyazott csatlakoztatási névtérben meghiúsul, ha a külső konténer maszkolta a /proc alrendszereket (/proc/acpi, /proc/kcore, /proc/keys), vagy a seccomp eldobta a mount(2) hívást:

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. A hiányzó /dev/fuse megtöri a fuse-overlayfs működését

A rootless konténermotorok, amelyek nem tudnak kernel overlayfs fájlrendszert csatlakoztatni, a fuse-overlayfs megoldásra térnek át. Minimális konténerekben vagy olyan Kubernetes podokban, amelyekben nincs /dev/fuse eszközátadás, a fuse-overlayfs azonnal meghiúsul:

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

Hogyan futtatja a gvx a docker:dind alkalmazást teljesen felhasználói térben

A gvx mind az öt kernel-akadályt megkerüli, mert nem kéri a host Linux kerneltől névterek létrehozását, fájlrendszerek csatlakoztatását vagy hálózati interfészek konfigurálását. Ehelyett a rungv egy belső, felhasználói térben futó Linux kernelt (a gVisor Sentry-t) és egy felhasználói térbeli hálózati vermet (netstack) futtat egyetlen, hagyományos, nem privilegizált folyamaton belül.

Unprivileged Docker-in-Docker futtatása a gvx-szel

1. Memórián belüli névterek és csatlakoztatási tábla (VFS2)

Amikor a dockerd, a containerd és a runc a rungv-n belül fut, a systrap elfogja a rendszerhívásaikat, és a folyamaton belüli Sentry kernelhez irányítja őket, nem pedig a host kernelhez:

  • Az unshare(2), a clone(2), a pivot_root(2), a chroot(2) és a mount(2) a Sentry memórián belüli feladathierarchiáján és VFS2 csatlakoztatási tábláján (procfs, sysfs, tmpfs, devpts, cgroupfs v2) működik, miközben a host rungv folyamat az Ön nem privilegizált host UID-je alatt fut.

2. Natív overlayfs egyfájlos ext4lite kötetekon

Amikor a -v gvx-docker:/var/lib/docker (vagy a --mount type=volume,src=/disk/gvx-docker.ext4,dst=/var/lib/docker) paramétert adja meg, a gvx a beépített ext4lite fájlrendszert csatlakoztatja a /var/lib/docker útvonalra.

Mivel az ext4lite egy JBD2 naplózott ext4 fájlrendszert valósít meg egyetlen host fájlban (gvx-docker.ext4), és támogatja a trusted.overlay.* kiterjesztett attribútumokat, a karakteres whiteout eszközöket (0:0), a d_type mezőt és a RENAME_EXCHANGE műveletet, a dockerd a vendég oldalon a saját natív overlayfs tárolóillesztőjét használja. A többlépcsős docker build műveletek Copy-on-Write rétegeket osztanak meg a /dev/fuse nélkül, és Docker vfs tartalék illesztőjének lemezterület-robbanása nélkül.

3. Felhasználói térbeli docker0 híd és iptables-legacy

Amikor a docker:dind elindul a gvx-en belül:

  • A vendég dockerd létrehozza a docker0 hidat (172.17.0.1/16), virtuális veth párokat csatol a beágyazott konténerekhez, és a gvx felhasználói térbeli netstack rétegében addrtype és conntrack illesztésekkel programozza a NAT (DOCKER, POSTROUTING) és FILTER láncokat.
  • A -p unix:~/.gvx/docker.sock:2375 megadása egy host Unix domain socketet köt (0600 mód), és a kapcsolatokat közvetlenül a homokozón belüli dockerd 2375 portjára továbbítja.

Összehasonlítás a meglévő konténer-eszközökkel

Képesség / korlátozásSzabványos Docker (dockerd)Rootless Docker / PodmanKaniko / Buildah (jogosultság nélkül)gvx (rungv + docker:dind)
Host root vagy sudo szükségesIgenNemNemNem
Működik PR_SET_NO_NEW_PRIVS=1 mellettNemNem (a newuidmap hibázik)RészbenIgen
Működik, ha az unshare(CLONE_NEWUSER) tiltott (EPERM)N/ANemBuildah: Nem / Kaniko: IgenIgen
Működik /dev/fuse nélkülIgen (kernel overlay2-t használ)Csak lassú vfs másolássalIgenIgen (overlayfs ext4lite-on)
Támogatja a docker build (BuildKit) parancsotIgenIgen (ha a userns engedélyezett)Csak image build (futtatás nélkül)Igen
Támogatja a docker run és a docker compose up parancsotIgenIgen (ha a userns engedélyezett)NemIgen
Fut Windows és macOS rendszeren Linux VM nélkülNem (WSL2 / VM szükséges)Nem (Linux VM szükséges)NemIgen (whpx, hvf, systrap)

Pontos host kernel követelmények Linuxon

A gvx nulla megemelt képességet (CapEff: 0000000000000000) és nulla felhasználói névteret igényel. Linux host esetén a rungv mindössze három szabványos, nem privilegizált kernel-primitívre támaszkodik:

  1. ptrace(PTRACE_ATTACH) a saját gyermekszálán egyszer, inicializáláskor: A systrap indításkor egy helyi stub segédszálat hoz létre, csatlakozik hozzá a megosztott memóriakontextus inicializálásához, majd leválik róla. Ha a host beállítja a kernel.yama.ptrace_scope = 3 értéket (ami rendszerszinten letiltja a ptrace hívásokat), vagy egy külső seccomp szűrő blokkolja a ptrace hívást, a systrap inicializálása nem tud befejeződni. (A yama.ptrace_scope = 1 beállítás mellett, amely az Ubuntu és a Debian alapértelmezettje, a gvx sikeresen fut, mert a szülő-gyermek nyomkövetés engedélyezett.)
  2. seccomp(SECCOMP_SET_MODE_FILTER): A konténer stub szálaiból érkező vendég rendszerhívások elfogására szolgál. Ahogy ennek a sorozatnak a 3. része ismerteti, a gvx működik akkor is, ha a SECCOMP_FILTER_FLAG_NEW_LISTENER elérhető, és akkor is, ha egy beágyazott homokozón belül EBUSY értéket ad vissza.
  3. mmap(..., PROT_EXEC, ...): A vendég ELF szegmensek és a systrap megosztott memória trampolinjának leképezésére szolgál.

Végpontok közötti példa: több konténeres alkalmazás építése és tesztelése root nélkül

Az alábbi szkript egy teljes docker build műveletet és egy kétkonténeres integrációs tesztet (redis + alkalmazáskonténer) futtat egy nem privilegizált felhasználói munkamenetben:

 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# Az image építése overlayfs használatával ext4lite fájlrendszeren
20docker build -t demo-ping:latest .
21
22# Hídhálózat létrehozása, a Redis indítása, és a konténerek közötti kapcsolat ellenőrzése
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# Kimenet: PONG
27
28# A munkaterhelést végző konténerek törlése és a homokozó leállítása
29docker rm -f cache
30docker network rm demo-net
31kill -INT $DIND_PID

További olvasnivaló ebben a sorozatban

  1. gvx: Linux-konténerek, Docker és Kubernetes futtatása egyetlen nem privilegizált folyamatban: A gvx architektúrájának áttekintése, platformfüggetlen végrehajtó motorjai (whpx, hvf, systrap), VFS2 (erofs, ext4lite, hostfs v2) és netstack komponensei.
  2. Docker, docker build és docker compose futtatása root vagy felhasználói névterek nélkül (ez a bejegyzés)
  3. Docker-in-Docker futtatása gVisoron és beágyazott homokozókban a gvx segítségével: Hogyan oldja meg a gvx a modprobe, az iptables-nft, az overlay2 a gofer-en, valamint a beágyazott SECCOMP_FILTER_FLAG_NEW_LISTENER (EBUSY) problémáit a gVisor (runsc) környezetben.
  4. Gyors, izolált Docker-környezetek AI-ügynökök RL-kipróbálásaihoz a gvx segítségével: Párhuzamos SWE-bench és RL-kipróbálási környezetek skálázása 100 milliszekundumos copy-on-write .ext4 kötetvisszaállítással.