Menjalankan Docker, docker build, dan docker compose Tanpa Root atau User Namespaces

Solusi Cepat: Jalankan Docker Tanpa Hak Istimewa dalam Tiga Langkah
Jika Anda bekerja di dalam container Linux yang terkunci, CI runner, Kubernetes Pod, atau sandbox agen AI tempat root, sudo, user namespace (unshare(CLONE_NEWUSER)), mount(2), dan /dev/fuse diblokir, gvx (rungv) adalah solusi yang aman dan berlapis pertahanan untuk menjalankan mesin docker:dind penuh di ruang pengguna (user space).
Mengapa
gvxAman secara Desain (Bukan Cara Eskalasi Hak Istimewa): Berbeda dengan memasang host/var/run/docker.sockatau menjalankandocker run --privileged(yang memberikan kendali setara root atas kernel host),gvxtidak melewati atau melemahkan kebijakan keamanan host mana pun (PR_SET_NO_NEW_PRIVS,seccomp, AppArmor, atau batas UID non-root). Sebaliknya,rungvmengunci proses host-nya sendiri (PR_SET_NO_NEW_PRIVS+ allowlist BPFseccompyang ketat) dan menjalankandockerddi dalam kernel user-space gVisor (Sentry) milik Google yang aman dari kesalahan memori. Seluruh kapabilitasUID 0di dalam guest, mountoverlayfs(ext4lite), dan aturaniptablestetap terisolasi secara ketat di dalam proses sandbox.
1# 1. Pasang rungv di ruang pengguna (rilis prebuilt ter-attest SLSA atau go install)
2# Opsi A: Verifikasi dan ekstrak binary prebuilt ter-attest SLSA dari 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# Opsi B: Atau pasang langsung dari source dengan Go
9CGO_ENABLED=0 GOBIN=~/.local/bin go install z.gfire.dev/gvx/cmd/rungv@latest
10
11# 2. Jalankan docker:dind di dalam gvx dengan volume ext4lite berupa satu file
12# Meneruskan ~/.gvx/docker.sock (mode 0600) ke port guest 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. Arahkan Docker CLI standar dan Docker Compose ke socket ruang pengguna
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 ... (containerized)
26
27docker build -t app:test .
28docker run --rm app:test
29docker compose up -d
Mengapa Alat Rootless Standar Gagal di Sandbox Terbatas
Ketika seorang engineer atau agen coding otonom perlu menjalankan docker build, docker run, atau docker compose di dalam container yang dikeraskan atau runner multi-tenant, solusi standar gagal pada lima hambatan kernel yang berbeda.
1. Tidak Ada Socket Docker Daemon di Host
Menjalankan docker ps atau docker build langsung gagal ketika /var/run/docker.sock host tidak di-mount ke dalam lingkungan:
1Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
2. PR_SET_NO_NEW_PRIVS Memblokir sudo dan Helper Setuid
Container yang dikeraskan (securityContext.allowPrivilegeEscalation: false di Kubernetes, --security-opt=no-new-privileges di Docker, atau sandbox exebox / bwrap) mengatur bit Linux PR_SET_NO_NEW_PRIVS pada pohon proses. Upaya eskalasi melalui sudo atau binary setuid (newuidmap, newgidmap, fusermount3) akan gagal:
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. Kebijakan Seccomp dan Sysctl Memblokir unshare(CLONE_NEWUSER)
Alat yang dipasarkan sebagai "rootless" (Rootless Docker, Podman, Buildah, nerdctl, bubblewrap) tetap bergantung pada user namespace Linux (CLONE_NEWUSER). Alat tersebut gagal setiap kali:
- Profil seccomp default container luar memblokir
unshare(2)atauclone(CLONE_NEWUSER). - Ubuntu 24.04+ mengaktifkan
kernel.apparmor_restrict_unprivileged_userns = 1. - Node Debian atau RHEL mengatur
kernel.unprivileged_userns_clone = 0atauuser.max_user_namespaces = 0. newuidmaptidak dapat menulis ke/proc/self/uid_mapkarenaPR_SET_NO_NEW_PRIVSaktif.
Galat yang dihasilkan terlihat seperti berikut:
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) Diblokir Tanpa CAP_SYS_ADMIN pada Host
Meskipun suatu lingkungan mengizinkan CLONE_NEWUSER, mount /proc baru di dalam mount namespace bersarang tetap gagal jika container luar telah menyembunyikan subtree /proc (/proc/acpi, /proc/kcore, /proc/keys) atau menghapus mount(2) dari 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. /dev/fuse yang Hilang Merusak fuse-overlayfs
Engine container rootless yang tidak dapat me-mount overlayfs kernel akan beralih ke fuse-overlayfs. Pada container minimal atau pod Kubernetes tanpa passthrough perangkat /dev/fuse, fuse-overlayfs langsung gagal:
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
Cara gvx Menjalankan docker:dind Sepenuhnya di Ruang Pengguna
gvx melewati kelima hambatan kernel tersebut karena tidak meminta kernel Linux host untuk membuat namespace, me-mount filesystem, atau mengonfigurasi antarmuka jaringan. Sebaliknya, rungv menjalankan kernel Linux internal berbasis ruang pengguna (gVisor Sentry) dan tumpukan jaringan ruang pengguna (netstack) di dalam satu proses unprivileged biasa.

1. Namespace dan Tabel Mount dalam Memori (VFS2)
Ketika dockerd, containerd, dan runc dijalankan di dalam rungv, systrap mencegat system call mereka dan mengarahkannya ke kernel Sentry dalam proses, bukan ke kernel host:
unshare(2),clone(2),pivot_root(2),chroot(2), danmount(2)beroperasi pada hierarki task dalam memori milik Sentry serta tabel mountVFS2(procfs,sysfs,tmpfs,devpts,cgroupfsv2), sementara proses hostrungvberjalan di bawah UID host unprivileged Anda.
2. overlayfs Native pada Volume ext4lite Berupa Satu File
Ketika Anda memberikan -v gvx-docker:/var/lib/docker (atau --mount type=volume,src=/disk/gvx-docker.ext4,dst=/var/lib/docker), gvx me-mount filesystem bawaan ext4lite pada /var/lib/docker.
Karena ext4lite mengimplementasikan filesystem ext4 berjurnal JBD2 di dalam satu file host (gvx-docker.ext4) dengan dukungan atribut terperluas trusted.overlay.*, perangkat whiteout karakter (0:0), d_type, dan RENAME_EXCHANGE, dockerd menggunakan driver penyimpanan overlayfs native di dalam guest. Operasi docker build multi-tahap berbagi layer Copy-on-Write tanpa /dev/fuse dan tanpa ledakan penggunaan ruang disk seperti pada driver fallback vfs Docker.
3. Bridge docker0 Ruang Pengguna dan iptables-legacy
Ketika docker:dind dimulai di dalam gvx:
dockerddi dalam guest membuat bridgedocker0(172.17.0.1/16), memasang pasanganvethvirtual untuk container bersarang, dan memprogram rantaiNAT(DOCKER,POSTROUTING) sertaFILTERdengan pencocokanaddrtypedanconntrackdi dalamnetstackruang pengguna milikgvx.- Opsi
-p unix:~/.gvx/docker.sock:2375mengikat socket Unix domain host (mode0600) dan meneruskan koneksi langsung ke port2375milikdockerddi dalam sandbox.
Perbandingan dengan Alat Container yang Ada
| Kapabilitas / Batasan | Docker Standar (dockerd) | Rootless Docker / Podman | Kaniko / Buildah (Unprivileged) | gvx (rungv + docker:dind) |
|---|---|---|---|---|
Memerlukan root atau sudo di host | Ya | Tidak | Tidak | Tidak |
Berfungsi dengan PR_SET_NO_NEW_PRIVS=1 | Tidak | Tidak (newuidmap gagal) | Sebagian | Ya |
Berfungsi ketika unshare(CLONE_NEWUSER) diblokir (EPERM) | Tidak berlaku | Tidak | Buildah: Tidak / Kaniko: Ya | Ya |
Berfungsi tanpa /dev/fuse | Ya (menggunakan overlay2 kernel) | Hanya melalui vfs yang lambat | Ya | Ya (overlayfs pada ext4lite) |
Mendukung docker build (BuildKit) | Ya | Ya (jika userns diizinkan) | Hanya pembuatan image (tanpa runtime) | Ya |
Mendukung docker run dan docker compose up | Ya | Ya (jika userns diizinkan) | Tidak | Ya |
| Berjalan di Windows dan macOS tanpa VM Linux | Tidak (memerlukan WSL2 / VM) | Tidak (memerlukan VM Linux) | Tidak | Ya (whpx, hvf, systrap) |
Persyaratan Kernel Host Linux yang Tepat
gvx tidak memerlukan kapabilitas istimewa apa pun (CapEff: 0000000000000000) dan tidak memerlukan user namespace. Pada host Linux, rungv hanya bergantung pada tiga primitif kernel unprivileged standar:
ptrace(PTRACE_ATTACH)pada thread child-nya sendiri satu kali selama inisialisasi:systrapmenjalankan thread helper stub lokal saat startup, melakukan attach padanya untuk menginisialisasi konteks memori bersama, lalu melakukan detach. Jika host mengaturkernel.yama.ptrace_scope = 3(yang menonaktifkan seluruhptracepada sistem) atau memblokirptracedalam filter seccomp luar, inisialisasisystraptidak dapat diselesaikan. (Denganyama.ptrace_scope = 1, nilai default di Ubuntu dan Debian,gvxberhasil karena tracing dari parent ke child diizinkan.)seccomp(SECCOMP_SET_MODE_FILTER): Digunakan untuk menangkap system call guest dari thread stub container. Sebagaimana dibahas dalam Bagian 3 seri ini,gvxberfungsi baik ketikaSECCOMP_FILTER_FLAG_NEW_LISTENERtersedia maupun ketika mengembalikanEBUSYdi dalam sandbox bersarang.mmap(..., PROT_EXEC, ...): Digunakan untuk memetakan segmen ELF guest dan trampolin memori bersamasystrap.
Contoh Lengkap: Membangun dan Menguji Aplikasi Multi-Container Tanpa Root
Skrip berikut menjalankan docker build lengkap dan pengujian integrasi dua container (redis + container aplikasi) di dalam sesi pengguna unprivileged:
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# Bangun image menggunakan overlayfs pada ext4lite
20docker build -t demo-ping:latest .
21
22# Buat jaringan bridge, jalankan Redis, dan verifikasi konektivitas antar container
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# Bersihkan container beban kerja dan hentikan sandbox
29docker rm -f cache
30docker network rm demo-net
31kill -INT $DIND_PID
Bacaan Lanjutan dalam Seri Ini
- gvx: Menjalankan Linux Container, Docker, dan Kubernetes dalam Satu Proses Unprivileged: Ikhtisar arsitektur
gvx, mesin eksekusi lintas platformnya (whpx,hvf,systrap),VFS2(erofs,ext4lite,hostfsv2), dannetstack. - Menjalankan Docker, docker build, dan docker compose Tanpa Root atau User Namespace (artikel ini)
- Menjalankan Docker-in-Docker di dalam gVisor dan Sandbox Bersarang dengan gvx: Cara
gvxmenyelesaikanmodprobe,iptables-nft,overlay2padagofer, danSECCOMP_FILTER_FLAG_NEW_LISTENERbersarang (EBUSY) di dalamgVisor(runsc). - Lingkungan Docker Terisolasi yang Cepat untuk Rollout RL Agen AI dengan gvx: Penskalaan lingkungan rollout RL dan
SWE-benchparalel dengan reset volume.ext4Copy-on-Write dalam 100 milidetik.