GoSuda

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

By Lemon Mint views ...

Solusi Cepat: Menjalankan Docker Tanpa Hak Istimewa dalam Tiga Langkah

Jika Anda bekerja di dalam container Linux yang terkunci, CI runner, Kubernetes Pod, atau sandbox agen pengodean AI (seperti lingkungan komputasi agen cloud) tempat root, sudo, user namespace (unshare(CLONE_NEWUSER)), mount(2), dan /dev/fuse diblokir, gvx (rungv) adalah solusi aman, berupaya rendah, dan efisien token untuk menjalankan mesin docker:dind penuh di ruang pengguna (user space).

Solusi Berupaya Rendah dan Efisien Token untuk Agen Pengodean AI: Ketika agen pengodean otonom menemui Cannot connect to the Docker daemon, upaya untuk memasang dan menambal docker.io, podman, atau rootlesskit di dalam container terbatas umumnya membuang 15 hingga 30 giliran pemanggilan alat dan puluhan ribu token konteks untuk berputar-putar melalui galat systemctl, ulimit, iptables, unshare, dan runc, hanya untuk gagal atau kembali menulis ulang Dockerfile secara manual. Dengan gvx (rungv), agen menjalankan satu bootstrap 3 langkah yang deterministik dalam satu giliran dan segera menjalankan perintah docker build, docker run, dan docker compose standar tanpa perubahan.

Mengapa gvx Aman secara Desain (Bukan Solusi Eskalasi Hak Istimewa): Berbeda dengan memasang /var/run/docker.sock milik host atau menjalankan docker run --privileged (yang memberikan kendali setara root atas kernel host), gvx tidak melewati atau melemahkan kebijakan keamanan host mana pun (PR_SET_NO_NEW_PRIVS, seccomp, AppArmor, atau batas UID non-root). Sebaliknya, rungv mengunci proses host-nya sendiri (PR_SET_NO_NEW_PRIVS + allowlist BPF seccomp yang ketat) dan menjalankan dockerd di dalam kernel ruang pengguna gVisor (Sentry) milik Google yang aman dari sisi memori. Seluruh kapabilitas UID 0 pada guest, mount overlayfs (ext4lite), dan aturan iptables tetap terisolasi secara ketat di dalam proses sandbox.

 1# 1. Pasang rungv di ruang pengguna (rilis prebuilt bersertifikasi SLSA atau go install)
 2# Opsi A: Verifikasi dan ekstrak binary prebuilt bersertifikasi 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 code 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 berkas tunggal
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# Keluaran: 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 pengodean otonom perlu menjalankan docker build, docker run, atau docker compose di dalam container yang diperkeras atau runner multi-tenant, solusi standar gagal pada lima hambatan kernel yang berbeda.

1. Tidak Ada Socket Docker Daemon di Host (systemctl dan service docker start Juga Gagal)

Menjalankan docker ps atau docker build gagal seketika ketika /var/run/docker.sock milik host tidak dipasang ke dalam lingkungan, dan upaya menjalankan docker.io melalui systemctl atau service docker start gagal karena PID 1 bukan systemd dan /etc/init.d/docker menabrak batas keras ulimit -n pada container:

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 Memblokir sudo dan Helper Setuid

Container yang diperkeras (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) 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 ketika:

  • Profil seccomp default container luar memblokir unshare(2) atau clone(CLONE_NEWUSER).
  • Ubuntu 24.04+ mengaktifkan kernel.apparmor_restrict_unprivileged_userns = 1.
  • Node Debian atau RHEL mengatur kernel.unprivileged_userns_clone = 0 atau user.max_user_namespaces = 0.
  • newuidmap tidak dapat menulis ke /proc/self/uid_map karena PR_SET_NO_NEW_PRIVS aktif.

Galat yang dihasilkan tampak 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) dan pivot_root(2) Diblokir Selama docker build Tanpa CAP_SYS_ADMIN pada Host

Bahkan jika lingkungan mengizinkan CLONE_NEWUSER atau dockerd dipaksa berjalan dengan --iptables=false --bridge=none --storage-driver=vfs, menjalankan docker build gagal pada instruksi RUN pertama karena pemasangan /proc baru atau pemanggilan pivot_root(2) di dalam mount namespace bersarang diblokir:

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. /dev/fuse yang Tidak Ada Merusak fuse-overlayfs

Engine container rootless yang tidak dapat memasang overlayfs kernel akan beralih ke fuse-overlayfs. Pada container minimal atau Kubernetes pod tanpa passthrough perangkat /dev/fuse, fuse-overlayfs gagal seketika:

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, memasang sistem berkas, atau mengonfigurasi antarmuka jaringan. Sebaliknya, rungv menjalankan kernel Linux internal ruang pengguna (gVisor Sentry) dan tumpukan jaringan ruang pengguna (netstack) di dalam satu proses tanpa hak istimewa yang biasa.

Menjalankan Docker-in-Docker tanpa hak istimewa dengan gvx

1. Namespace dan Tabel Mount dalam Memori (VFS2)

Ketika dockerd, containerd, dan runc dijalankan di dalam rungv, systrap mencegat pemanggilan sistem mereka dan mengarahkannya ke kernel Sentry dalam proses, bukan ke kernel host:

  • unshare(2), clone(2), pivot_root(2), chroot(2), dan mount(2) beroperasi pada hierarki tugas dalam memori milik Sentry dan tabel mount VFS2 (procfs, sysfs, tmpfs, devpts, cgroupfs v2), sementara proses host rungv berjalan di bawah UID host tanpa hak istimewa Anda.

2. overlayfs Native pada Volume ext4lite Berkas Tunggal

Ketika Anda memberikan -v gvx-docker:/var/lib/docker (atau --mount type=volume,src=/disk/gvx-docker.ext4,dst=/var/lib/docker), gvx memasang sistem berkas ext4lite bawaannya di /var/lib/docker.

Karena ext4lite mengimplementasikan sistem berkas ext4 dengan jurnal JBD2 di dalam satu berkas 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 disk seperti pada driver fallback vfs Docker.

3. Bridge docker0 Ruang Pengguna dan iptables-legacy

Ketika docker:dind dimulai di dalam gvx:

  • dockerd pada guest membuat bridge docker0 (172.17.0.1/16), melampirkan pasangan veth virtual untuk container bersarang, dan memprogram rantai NAT (DOCKER, POSTROUTING) serta FILTER dengan pencocokan addrtype dan conntrack di dalam netstack ruang pengguna milik gvx.
  • Opsi -p unix:~/.gvx/docker.sock:2375 mengikat socket Unix domain host (mode 0600) dan meneruskan koneksi langsung ke port 2375 milik dockerd di dalam sandbox.

Perbandingan dengan Alat Container yang Ada

Kemampuan / BatasanDocker Standar (dockerd)Rootless Docker / PodmanKaniko / Buildah (Tanpa Hak Istimewa)gvx (rungv + docker:dind)
Memerlukan root atau sudo di hostYaTidakTidakTidak
Berfungsi dengan PR_SET_NO_NEW_PRIVS=1TidakTidak (newuidmap gagal)SebagianYa
Berfungsi ketika unshare(CLONE_NEWUSER) diblokir (EPERM)Tidak berlakuTidakBuildah: Tidak / Kaniko: YaYa
Berfungsi tanpa /dev/fuseYa (menggunakan overlay2 kernel)Hanya melalui vfs copy yang lambatYaYa (overlayfs pada ext4lite)
Mendukung docker build (BuildKit)YaYa (jika userns diizinkan)Hanya pembuatan image (tanpa runtime)Ya
Mendukung docker run dan docker compose upYaYa (jika userns diizinkan)TidakYa
Berjalan di Windows dan macOS tanpa VM LinuxTidak (memerlukan WSL2 / VM)Tidak (memerlukan VM Linux)TidakYa (whpx, hvf, systrap)

Persyaratan Kernel Host Linux yang Tepat

gvx tidak memerlukan kapabilitas yang ditingkatkan (CapEff: 0000000000000000) dan tidak memerlukan user namespace. Pada host Linux, rungv hanya bergantung pada tiga primitif kernel standar tanpa hak istimewa:

  1. ptrace(PTRACE_ATTACH) pada thread anak miliknya sendiri satu kali selama inisialisasi: systrap membuat thread stub helper lokal saat startup, melampirkan diri ke thread tersebut untuk menginisialisasi konteks memori bersama, lalu melepaskannya. Jika host mengatur kernel.yama.ptrace_scope = 3 (yang menonaktifkan semua ptrace secara sistem) atau memblokir ptrace dalam filter seccomp luar, inisialisasi systrap tidak dapat diselesaikan. (Di bawah yama.ptrace_scope = 1, nilai default di Ubuntu dan Debian, gvx berhasil karena tracing dari induk ke anak diizinkan.)
  2. seccomp(SECCOMP_SET_MODE_FILTER): Digunakan untuk menangkap pemanggilan sistem tamu dari thread stub container. Sebagaimana dibahas dalam Bagian 3 seri ini, gvx berfungsi baik ketika SECCOMP_FILTER_FLAG_NEW_LISTENER tersedia maupun ketika mengembalikan EBUSY di dalam sandbox bersarang.
  3. mmap(..., PROT_EXEC, ...): Digunakan untuk memetakan segmen ELF tamu dan trampolin memori bersama systrap.

Contoh End-to-End: 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 tanpa hak istimewa:

 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# Keluaran: 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

  1. gvx: Menjalankan Linux Container, Docker, dan Kubernetes dalam Satu Proses Tanpa Hak Istimewa: Ikhtisar arsitektur gvx, engine eksekusi lintas platformnya (whpx, hvf, systrap), VFS2 (erofs, ext4lite, hostfs v2), dan netstack.
  2. Menjalankan Docker, docker build, dan docker compose Tanpa Root atau User Namespace (artikel ini)
  3. Menjalankan Docker-in-Docker di Dalam gVisor dan Sandbox Bersarang dengan gvx: Cara gvx menyelesaikan modprobe, iptables-nft, overlay2 pada gofer, dan SECCOMP_FILTER_FLAG_NEW_LISTENER bersarang (EBUSY) di dalam gVisor (runsc).
  4. Lingkungan Docker Terisolasi yang Cepat untuk Rollout RL Agen AI dengan gvx: Penskalaan lingkungan rollout RL dan SWE-bench paralel dengan reset volume .ext4 Copy-on-Write dalam 100 milidetik.