---
id: e62d78ef5850c982dbddc9d3ff9134ae
author: Lemon Mint
title: 'gvx: Linux Containers, Docker en Kubernetes uitvoeren in één Unprivileged Process'
description: Technisch overzicht van gvx, een door beveiliging versterkte, platformonafhankelijke containerruntime en Go SDK, gebouwd op de gVisor user-space kernel, die Linux-containers, Docker-in-Docker en high-availability Kubernetes met meerdere knooppunten veilig uitvoert in één onbevoegd proces op Windows, macOS en Linux.
language: nl
date: 2026-11-06T12:02:56.008516536Z
path: /blog/posts/gvx-cross-platform-linux-containers-z48916d01
go_package: z.gfire.dev/gvx
go_repourl: https://github.com/gfire-sigs/gvx.git
category: lowlevel
---

## Inleiding: Beveiligde containers zonder root of host-daemons

Het uitvoeren van Linux-containers, `docker build` of Kubernetes binnen een ontwikkelmachine, CI-runner of multi-tenant cloudnode dwingt doorgaans een ongemakkelijke beveiligingsafweging af:

- Op **Linux** vereisen standaard OCI-runtimes (`runc`, `crun`, `runsc`) ofwel `root`-privileges, blootstelling van de host-socket `/var/run/docker.sock`, `--privileged` (`CAP_SYS_ADMIN`), of gebruikersnamespaces (`unshare(CLONE_NEWUSER)`) die het aanvalsoppervlak van de host-kernel vergroten.
- Op **Windows** en **macOS** starten containerengines (`Docker Desktop`, `Podman Machine`, `Lima`, `OrbStack`) een volledige Linux-virtuele-machinekernel binnen WSL2, Hyper-V of `Virtualization.framework` en draaien ze een persistente achtergronddaemon binnen die VM.

**[gvx](https://github.com/gfire-sigs/gvx)** (`rungv` CLI en de `z.gfire.dev/gvx/pkg/gvx` Go SDK) biedt een **veilig, zero-privilege alternatief**. Gebouwd als een upstream-traceerbare fork van de user-space Linux-kernel (`Sentry`) en de user-space netwerkstack (`netstack`) van Google's **gVisor**, voert `gvx` onveranderde `linux/amd64`- en `linux/arm64`-ELF64-binaries en OCI-containers rechtstreeks uit binnen **één niet-geprivilegieerd, zelf vergrendeld hostproces** op Windows, macOS en Linux.

> **Beveiligingsgarantie (Drieringsverdediging in de diepte)**: `gvx` tast nooit de beveiligingsgrenzen van het host-besturingssysteem aan, installeert nooit kernelstuurprogramma's en vereist nooit `root`, `sudo`, `--privileged` op de host, of `CLONE_NEWUSER`. Voordat één gastinstructie wordt uitgevoerd, vergrendelt `gvx` zijn eigen hostproces met Windows Restricted Tokens en Job Objects, macOS Seatbelt (`deny default`), of Linux `PR_SET_NO_NEW_PRIVS` + BPF `seccomp`. Alle systeemaanroepen van de gast, virtuele `UID 0`-privileges, mounts (`VFS2`) en netwerktabellen (`netstack`) zijn strikt beperkt binnen de geheugenveilige Go `Sentry`-kernel.

| Runtime                    | Host OS                                               |        Koude start | Geheugenverbruik | Beheer- of `sudo` vereist | Achtergrond-VM-daemon | Directe OCI-image uitvoeren |
| :------------------------- | :---------------------------------------------------- | ----------------: | ---------------: | :--------------------- | :------------------- | :------------------- |
| **`gvx` (`whpx` / `hvf`)** | Windows (`amd64`, `arm64`) & macOS (`arm64`)          |          `~20 ms` |        `~30 MiB` | Nee                    | Nee                  | Ja                   |
| **`gvx` (`systrap`)**      | Windows (`amd64`, `arm64`) & Linux (`amd64`, `arm64`) |    `~25 tot 65 ms` |        `~31 MiB` | Nee                    | Nee                  | Ja                   |
| **WSL2 / Docker Desktop**  | Windows & macOS                                       |  `800 tot 2500 ms` |      `> 512 MiB` | Ja (initiële installatie) | Ja                   | Vereist daemon       |
| **QEMU (Full System)**     | Windows & macOS                                       | `1500 tot 4000 ms` |      `> 256 MiB` | Nee                    | Nee                  | Vereist schijfimage  |

Er wordt geen Linux-VM-kernel gestart op Windows of macOS. Er draait geen achtergronddaemon op de host. Voor het host-besturingssysteem zijn geen `root`, `sudo`, gebruikersnamespaces (`CLONE_NEWUSER`), `mount(2)`, `TUN`/`TAP`-stuurprogramma's of `CAP_NET_ADMIN`-privileges vereist. Binnen dat niet-geprivilegieerde proces draait `gvx` **Docker-in-Docker (`docker:dind`)**, `docker build`, `docker compose` en **high-availability Kubernetes met meerdere nodes (`k3s` met ingebedde `etcd` en `Calico` CNI)**.

---

## Levenscyclus van de container en driedelige hostvergrendeling

Elke `gvx`-sandbox draait binnen één niet-geprivilegieerd hostproces en handhaaft een driefasige levenscyclus: vooraf openen van alle vereiste host-bestandsdescriptors en sockets, vergrendelen van het host-besturingssysteemproces via `pkg/hostlockdown`, en betreden van de in-proces `Sentry`-uitvoeringslus.

![gvx-containerlevenscyclus en zelfvergrendeling van de host](/assets/images/gvx/gvx-lifecycle-lockdown.png)

Voordat de controle wordt overgedragen aan de eerste gastinstructie, opent `gvx` vooraf zijn gecachte `.erofs`-imagelaagdescriptors, `.ext4`-volumebestandsdescriptors, de `/workspace` `*os.Root`-handle en host-netwerksockets, en roept vervolgens `hostlockdown.Apply()` aan:

1. **Windows NT (`lockdown_windows.go`)**: Roept `AdjustTokenPrivileges` aan met `SE_PRIVILEGE_REMOVED` om privileges ter plaatse te verwijderen, koppelt een `DISABLE_MAX_PRIVILEGE` beperkt impersonatietoken met Low-integriteit (`S-1-16-4096`), wijst het proces toe aan een anoniem Job Object met `JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 1` (waarmee het aanmaken van kindprocessen wordt geblokkeerd), en activeert `DisallowWin32kSystemCalls = 1` via `SetProcessMitigationPolicy`.
2. **macOS XNU (`lockdown_darwin.go`)**: Stelt `RLIMIT_NPROC = 0` in en past een Seatbelt-profiel (`sandbox_init_with_parameters`) toe, beginnend bij `(version 1)(deny default)`, dat `process-fork`, `process-exec*` en alle nieuwe host-bestandsopeningen blokkeert.
3. **Linux (`lockdown_linux.go` + `pkg/gvx/syscallfilter_linux.go`)**: Stelt `PR_SET_NO_NEW_PRIVS` in en installeert de Sentry BPF `seccomp`-allowlist over alle threads (`SECCOMP_FILTER_FLAG_TSYNC`) met expliciete `EPERM`-regels voor `execve`, `execveat`, `clone`, `openat` en `socket`.

---

## Systeemaanroepenonderschepping per platform en 4 KB-paging (`pkg/sentry/platform`)

Linux ELF64-binaries gaan uit van een geheugenpaginagranulariteit van 4 KB (`0x1000`) voor `mmap(MAP_FIXED)`-segmenttoewijzingen. Windows `VirtualAlloc` en `MapViewOfFile3` dwingen echter een uitlijning van 64 KB (`0x10000`) af, en Apple Silicon macOS (`darwin/arm64`) gebruikt host-pagina's van 16 KB (`0x4000`). Bovendien vereist elk besturingssysteem een ander mechanisme om Linux `SYSCALL`- (`amd64`) en `SVC #0`- (`arm64`) instructies te onderscheppen zonder een Linux-VM te starten.

`gvx` lost beide problemen op over vier uitvoeringsbackends die `pkg/sentry/platform.Context` implementeren:

![gvx-mechanica van platformsysteemaanroeponderschepping en 4KB-paging](/assets/images/gvx/gvx-platform-syscalls.png)

### 1. Windows-hardware-engine: `platform/whpx` (`WinHvPlatform.dll`)

Op `windows/amd64` en `windows/arm64` creëert `platform/whpx` via `WHvCreatePartition` een lichtgewicht hypervisorpartitie zonder een gastbesturingssysteemkernel op te starten:

- **Ontkoppelaar voor 64 KB-naar-4 KB-paging**: `whpx` registreert elke 64 MiB-arena van `pgalloc.MemoryFile` eenmalig bij de partitie via `WHvMapGpaRange`. Volgende `MapFile`- en `Unmap`-aanroepen wijzigen alleen de in-partitie gast-paginatabellen en dwingen exacte 4 KB-`R/W/X`-rechten af, ondanks de toewijzingsgranulariteit van Windows van 64 KB.
- **Registeruitwisseling zonder API via `CommPage`**:
  - Op `amd64` springt een `SYSCALL` van gast-Ring-3 naar een in-partitie Ring-0 `MSR_LSTAR`-stub (`stubgen_x86.go`), die de snelpad-syscall-GPR's (`RAX, RDI, RSI, RDX, R10, R8, R9, RIP, RSP`) naar een gedeelde 4 KB-`CommPage` schrijft en `HLT` uitvoert om `WHvRunVirtualProcessor` te verlaten.
  - Op `arm64` springt een gast-EL0 `SVC #0` naar EL1-vectoren (`stubgen_a64.go`), schrijft `X0..X8, SP_EL0, ELR_EL1, PSTATE` naar `CommPage`, en laadt vanaf een niet-gekoppeld GPA-nul om een geheugenexit terug naar de Sentry te activeren.

### 2. macOS-hardware-engine: `platform/hvf` (`Hypervisor.framework`)

Op Apple Silicon (`darwin/arm64`) voert `platform/hvf` containerthreads uit binnen `Hypervisor.framework`-vCPU's (`hv_vm_create`, `hv_vcpu_run`):

- **Tweetraps 4 KB-over-16 KB-MMU-vertaling**: Stage-2 (`hv_vm_map`) koppelt eenmaal 1 GiB-chunks van het geheugenbestand aan de Intermediate Physical Address (IPA)-ruimte met een granulariteit van 16 KB host-pagina's met `HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC`. Binnen de vCPU configureert de EL1 `bluepill`-stub (`bluepill_arm64.go`) `TCR_EL1.TG0 = 0b00` (4 KB-granule) in `TTBR0_EL1` en vult 4 KB Stage-1 paginatabelitems met exacte `R-X`- of `RW-` (`UXN=1`)-rechten. Omdat de ARM64-MMU de doorsnede van Stage-1- en Stage-2-rechten afdwingt, onderschept de hardware rechtenfouten op exacte 4 KB-grenzen.
- **Syscall-onderschepping**: Een gast-EL0 `SVC #0` gaat naar EL1 `VBAR_EL1`, schrijft registers naar de gedeelde 4 KB-`CommPage` en voert `HVC #0` uit om vanuit `hv_vcpu_run` terug te keren naar de Go Sentry-thread.

### 3. Windows user-mode-fallback: `platform/systrap` (`winsystrap`)

Wanneer hardwarevirtualisatie niet beschikbaar is (zoals binnen geneste cloud-VM's), voert `winsystrap` gastcode uit in user mode op `windows/amd64` en `windows/arm64`:

- **Hardware-`CR3`- / `TTBR0_EL1`-isolatie**: Gastthreads draaien binnen geïsoleerde stub-subprocessen die worden gestart vanuit een gegenereerd uitvoerbaar bestand van 1 KB (`stubimage_xplat.go`), beperkt door een token met Low-integriteit en een Job Object.
- **Patchen van binaries ter plaatse & `winSysmsg` IPC**: Op `amd64` vervangt de patcher (`patcher_amd64_xplat.go`) 2-byte `syscall`- (`0f 05`) instructies door 5-byte `jmp rel32`-sprongen (of `CC 90` breekpunt-traps wanneer een 5-byte-venster niet beschikbaar is) naar een snelpad-eiland. Op `arm64` wordt `svc #0` gepatcht met een `B`-branch naar een eiland-slot. Het eiland schrijft registers naar de gedeelde `winSysmsg`-pagina en synchroniseert met de Sentry via `WaitOnAddress` en `WakeByAddressSingle`, terwijl ongepatchte traps en paginafouten stoppen op een Windows Debug Object (`WaitForDebugEventEx`).

### 4. Linux user-mode-engine: `platform/systrap`

Op `linux/amd64` en `linux/arm64` voert `systrap` gastthreads (`sysmsg`) uit die systeemaanroepen van de gast onderscheppen via `SECCOMP_RET_TRAP` (`SIGSYS`) en `syscall`-locaties binair patchen naar een trampoline in gedeeld geheugen (`sysmsg`), gesynchroniseerd via `SYS_FUTEX`. Een stub-`syscallThread` (`syscall_thread.go`) voert adresruimtebewerkingen (`mmap`, `munmap`, `clone`) uit via `SECCOMP_RET_USER_NOTIF` (`_RUN_SECCOMP_LOOP`). Wanneer `gvx` draait binnen een buitenste `gVisor` (`runsc`)-sandbox waarin de enkele `SECCOMP_FILTER_FLAG_NEW_LISTENER`-plek `EBUSY` retourneert, schakelt `gvx` automatisch `syscallThread` over naar een futex-lus in gedeeld geheugen (`_RUN_SYSCALL_LOOP`), zoals beschreven in [deel 3 van deze serie](/blog/posts/docker-in-docker-inside-gvisor-with-gvx-z48916d03).

---

## Hoe `gvx` Linux-systeemaanroepen van de gast koppelt aan virtuele subsystemen en host-handles

Zodra een platformengine een `SYSCALL` (`amd64`) of `SVC #0` (`arm64`)-instructie van de gast onderschept en de gastregisters naar de 4 KB-gedeelde pagina schrijft (`CommPage`, `sysmsg` of `winSysmsg`), keert de controle terug naar de Go `Sentry`-taakgoroutine (`pkg/sentry/kernel/task_syscall.go`). In plaats van Linux-systeemaanroepen door te sturen naar de onderliggende host-besturingssysteemkernel, slaat `Task.doSyscall()` de oorspronkelijke registertoestand op (`SyscallSaveOrig()`), evalueert eventuele in-gast BPF `seccomp`-filters en `ptrace`-stops, en verdeelt het systeemaanroepnummer via `linux.AMD64` of `linux.ARM64` (`pkg/sentry/syscalls/linux/linux64.go`, met ongeveer 370 Linux-systeemaanroepen) naar vier interne domeinen:

![Hoe gvx Linux-systeemaanroepen van de gast koppelt aan subsystemen en het host-OS](/assets/images/gvx/gvx-syscall-mapping.png)

| Systeemaanroepdomein | Representatieve Linux-systeemaanroepen van de gast | Intern `gvx`-subsysteem (`pkg/sentry`) | Interactie met de host-OS-grens (na `hostlockdown`) |
| :--- | :--- | :--- | :--- |
| **A. Proces, namespace, mount en synchronisatie** | `clone`, `execve`, `unshare`, `setns`, `mount`, `umount2`, `pivot_root`, `setuid`, `capset`, `futex`, `epoll_wait`, `pipe2` | `kernel.Task`, virtuele credentials, futex-tabel en in-memory `VFS2` (`procfs`, `sysfs`, `cgroupfs` v2, `tmpfs`, `overlayfs`) | **Nul host-systeemaanroepen** (100% in-memory Go-status; volledig onzichtbaar voor het host-besturingssysteem) |
| **B. Virtueel geheugen (`MM`)** | `mmap`, `munmap`, `mremap`, `mprotect`, `brk`, `madvise`, `memfd_create` | `mm.MemoryManager` (4 KB VMA-boom) & `pgalloc.MemoryFile` | Bidirectionele 4 KB-paginatabelupdates via `WHvMapGpaRange`, `hv_vm_map` + `TTBR0_EL1`, of stub-`mmap`/`mprotect` |
| **C. Bestanden en opslag (`VFS2`)** | `openat`, `pread64`, `pwrite64`, `getdents64`, `statx`, `renameat2`, `setxattr`, `mknod`, `inotify_add_watch` | `vfs.VirtualFilesystem` mounttabel-router (`fsimpl/erofs`, `fsimpl/ext4lite`, `fsimpl/hostfs` v2) | Bidirectionele `pread`/`pwrite` op 1 vastgezette `.erofs`-FD of 1 `.ext4`-FD, of begrensde relatieve doorlopen op `*os.Root` |
| **D. Netwerken & Netfilter** | `socket`, `bind`, `listen`, `connect`, `sendmsg`, `recvmsg`, `netlink`, `setsockopt(IPT_SO_SET_REPLACE)` | User-space `pkg/tcpip` (`lo`, `eth0`, `docker0`, `veth`, `vxlan`, `wireguard`, `ipset`, `iptables-legacy`) | Verkeer binnen de sandbox gebruikt **nul host-systeemaanroepen**; extern verkeer wordt gekoppeld aan `net.Dial`/`net.Listen` (`-net=nat`) of 1 UDP-socket (`-net=wg`) |

Wanneer de handler `(rval, ctrl, err)` retourneert, zet `Task.doSyscallInvoke()` elke fout om in een negatieve Linux-`errno` (`-ExtractErrno(err, sysno)`), schrijft de retourwaarde terug naar de gedeelde registerpagina (`RAX` op `amd64`, `X0` op `arm64`) en hervat de uitvoering van de gast.

---

## Opslag (`VFS2`) en tweesporen user-space-netwerken (`netstack`)

Alle bestands- en netwerkbewerkingen van de gast worden afgehandeld binnen de Go `Sentry` via drie `VFS2`-bestandssystemen en twee `pkg/netbackend`-sporen:

![gvx VFS2-opslagengines en tweesporen netstack](/assets/images/gvx/gvx-storage-netstack.png)

| Opslagengine | Mountrol in `gvx` | Onderliggende hostbron | Host-aanroepen van `openat` / `NtCreateFile` tijdens uitvoering | Windows Defender (`WdFilter.sys`) scans per bestand |
| :--- | :--- | :--- | -----------------------------------------------: | -----------------------------------------------: |
| **`fsimpl/erofs`** | Alleen-lezen OCI-imagelagen (onderste lagen) | Eén `<sha256>.erofs`-bestand per laag | `0` | `0` |
| **`fsimpl/ext4lite`** | Benoemde volumes (`-v name:/path`) | Eén `<name>.ext4`-bestand per volume | `0` | `0` |
| **`fsimpl/hostfs` v2** | Hostworkspace (`-workspace`, `-v /host:/guest`) | Vastgezette `*os.Root`-hostmap | `O(depth)` per niet-gecachte opening | `1` per hostbestandssluiting |

### Waarom `ext4lite` belangrijk is voor Docker, databases en pakketbeheerders

Het uitpakken of schrijven van tienduizenden containerbestanden rechtstreeks naar Windows NTFS of macOS APFS veroorzaakt scans door antivirus-minifilters (`WdFilter.sys`), botsingen door hoofdlettergevoeligheid en ontbrekende POSIX-uitgebreide attributen.

`pkg/sentry/fsimpl/ext4lite` implementeert een pure-Go `ext4`-bestandssysteem binnen één vooraf geopend hostbestand (`%LOCALAPPDATA%\gvx\cache\volumes\<name>.ext4` op Windows, `~/Library/Caches/gvx/volumes/<name>.ext4` op macOS, of `~/.cache/gvx/volumes/<name>.ext4` op Linux) met:

- **4 KiB-blokken en dynamische blokgroepen van 16 MiB (`meta_bg`)**: Groeit dynamisch zonder stilstand door toewijzing van sparse-bestanden (`fallocate` op Linux, `fcntl(F_PREALLOCATE)` op macOS, `FileAllocationInfo` op Windows) en comprimeert ongebruikte groepen aan het einde bij een schone unmount.
- **JBD2-journal in ordered-modus (inode 8)**: Atomaire transactiecommits met CRC-32-checksums en revoke-blokken, plus `fsckLite`-herstel.
- **Ondersteuning voor `overlayfs`-bovenlagen**: Implementeert `trusted.overlay.*`- en `security.capability`-uitgebreide attributen, whiteouts voor tekenapparaten (`0:0`), `d_type`-rapportage van directory-items en `RENAME_EXCHANGE`.

---

## Praktische toepassingen: Docker Engine, Kubernetes (`k3s` + `Calico`) en Go SDK

### `rungv` installeren: SLSA-geattesteerde vooraf gebouwde releases of `go install`

U kunt een vooraf gebouwd `rungv`-archief downloaden voor `linux/amd64`, `linux/arm64`, `darwin/arm64`, `windows/amd64` of `windows/arm64` via [GitHub Releases](https://github.com/gfire-sigs/gvx/releases) (elk gebouwd door de SLSA-releasepipeline met een Sigstore-herkomstbundel en `SHA256SUMS`), of installeer rechtstreeks vanuit de broncode met `go install`:

```sh
# Optie A: Download een vooraf gebouwde release en verifieer de SLSA-buildherkomst
gh attestation verify rungv-v0.2.0-linux-amd64.tar.gz --repo gfire-sigs/gvx \
  --signer-workflow gfire-sigs/gvx/.github/workflows/release.yml \
  --source-ref refs/tags/v0.2.0 --deny-self-hosted-runners
shasum -a 256 -c SHA256SUMS --ignore-missing
tar -xzf rungv-v0.2.0-linux-amd64.tar.gz

# Optie B: Installeer rechtstreeks via Go (Linux / Windows)
CGO_ENABLED=0 go install z.gfire.dev/gvx/cmd/rungv@latest
```

> Op macOS (`darwin/arm64`) is het vooraf gebouwde releasearchief al ondertekend met de `com.apple.security.hypervisor` entitlement (`xattr -d com.apple.quarantine rungv` verwijdert de browserquarantaine). Als u lokaal bouwt met `go install` of `go build` op macOS, onderteken de binary dan met `codesign --sign - --entitlements entitlements.plist --force $(which rungv)`.

### 1. Een niet-geprivilegieerde Docker Engine uitvoeren (`docker:dind`)

Volgens [`docs/docker-engine.md`](https://github.com/gfire-sigs/gvx/blob/main/docs/docker-engine.md) kunt u een onveranderde `docker:dind`-container binnen `rungv` uitvoeren op Windows, macOS of Linux en deze besturen met uw host-`docker`-CLI:

```sh
# 1. Maak de hostdirectory aan voor de doorgestuurde Unix-socket
mkdir -p ~/.gvx

# 2. Start docker:dind binnen een gvx-sandbox met een ext4lite-volume
rungv run \
  -p unix:~/.gvx/docker.sock:2375 \
  -p 127.0.0.1:9000-9019:9000-9019 \
  -v gvx-docker:/var/lib/docker \
  -e DOCKER_TLS_CERTDIR= \
  docker:dind --tls=false
```

In een tweede terminal richt u de host-`docker`-CLI op de sandbox-socket:

```sh
docker context create gvx --docker host=unix://$HOME/.gvx/docker.sock
docker context use gvx

docker info --format '{{.Driver}} {{.OperatingSystem}}'
# Uitvoer: overlayfs Alpine Linux ... (gecontaineriseerd)

docker build -t myapp ./app
docker compose up -d
```

### 2. Kubernetes (`k3s` + `Calico`) uitvoeren in niet-geprivilegieerde sandboxes

Omdat `gvx` `/dev/kmsg`, `cgroup` v2 (`memory.max` OOM-killer en `cpu.max`-bandbreedtebeperking), `/proc/diskstats`, `wireguard`- en `vxlan`-netlink-apparaten, `ipset` en `iptables-legacy` (`addrtype`, `conntrack`, `statistic`, `recent`) implementeert, bereikt een onveranderde `rancher/k3s`-image de status `Ready` binnen één `rungv`-proces:

```sh
mkdir -p ~/.gvx/k3s

rungv run \
  -e IPTABLES_MODE=legacy \
  -p 127.0.0.1:6443:6443 \
  -p 127.0.0.1:30000-30019:30000-30019 \
  -v k3s:/var/lib/rancher \
  --mount type=bind,src=$HOME/.gvx/k3s,dst=/output \
  rancher/k3s:v1.31.4-k3s1 server \
  --disable=traefik,servicelb \
  --write-kubeconfig=/output/kubeconfig.yaml \
  --write-kubeconfig-mode=644
```

U kunt ook meerdere `gvx`-nodes via WireGuard samenvoegen (`flannel-backend=wireguard-native` of een `wg0`-mesh) met high availability via ingebedde `etcd`, of **Calico** draaien (`calico-vxlan.yaml` met `FELIX_IPTABLESBACKEND=Legacy`) om Kubernetes `NetworkPolicy` volledig binnen de user space af te dwingen.

### 3. Linux-containers in Go insluiten via `z.gfire.dev/gvx/pkg/gvx`

Go-applicaties kunnen Linux-containers rechtstreeks insluiten zonder externe containerdaemon:

```go
package main

import (
	"context"
	"fmt"
	"os"

	"z.gfire.dev/gvx/pkg/gvx"
)

func main() {
	ctx := context.Background()
	sb, err := gvx.New(ctx, gvx.Config{
		Platform:      gvx.PlatformAuto,
		NetworkMode:   gvx.NetModeNAT,
		OCIImage:      "alpine:3.20",
		WorkspacePath: "./repo",
		Argv:          []string{"/usr/bin/git", "status"},
		Stdout:        os.Stdout,
		Stderr:        os.Stderr,
	})
	if err != nil {
		fmt.Fprintf(os.Stderr, "init sandbox: %v\n", err)
		os.Exit(1)
	}
	defer sb.Close()

	exitCode, err := sb.Run(ctx)
	if err != nil {
		fmt.Fprintf(os.Stderr, "run sandbox: %v\n", err)
		os.Exit(1)
	}
	os.Exit(exitCode)
}
```

---

## Verder lezen in deze serie

1. **[gvx: Linux-containers, Docker en Kubernetes uitvoeren in één niet-geprivilegieerd proces](/blog/posts/gvx-cross-platform-linux-containers-z48916d01)** (dit bericht)
2. **[Docker, docker build en docker compose uitvoeren zonder root of gebruikersnamespaces](/blog/posts/run-docker-without-root-or-userns-gvx-z48916d02)**: Hoe `docker:dind` wordt gebootstrapt in afgeschermde sandboxes waar `sudo`, `unshare(CLONE_NEWUSER)`, `mount(2)` en `/dev/fuse` zijn geblokkeerd.
3. **[Docker-in-Docker uitvoeren binnen gVisor en geneste sandboxes met gvx](/blog/posts/docker-in-docker-inside-gvisor-with-gvx-z48916d03)**: Waarom `apt-get install docker.io` en geneste `runsc` binnen `gVisor` falen over vijf kernelbarrières, en hoe `gvx` geneste `docker:dind` uitvoert met een futex-lus in gedeeld geheugen.
4. **[Snelle geïsoleerde Docker-omgevingen voor AI-agent RL-rollouts met gvx](/blog/posts/fast-docker-environments-for-agent-rl-rollouts-z48916d04)**: Het opschalen van `SWE-bench`- en agent-reinforcement-learning-rollouts met honderden parallelle niet-geprivilegieerde `docker:dind`-instanties en copy-on-write `.ext4`-volumeresets van 100 milliseconden.
