---
id: e62d78ef5850c982dbddc9d3ff9134ae
author: Lemon Mint
title: 'gvx: Executando Linux Containers, Docker e Kubernetes em um Único Processo Não Privilegiado'
description: Visão técnica geral do gvx, um runtime de contêineres multiplataforma e SDK em Go reforçado em termos de segurança, construído sobre o kernel em espaço de usuário gVisor, que executa com segurança contêineres Linux, Docker-in-Docker e clusters Kubernetes de alta disponibilidade com múltiplos nós em um único processo não privilegiado, nos sistemas Windows, macOS e Linux.
language: pt
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
---

## Introdução: Contêineres Endurecidos com Segurança Sem Root ou Daemons no Host

Executar contêineres Linux, `docker build` ou Kubernetes dentro de uma máquina de desenvolvimento, de um runner de CI ou de um nó de nuvem multilocatário normalmente impõe um compromisso de segurança desconfortável:

- No **Linux**, runtimes OCI padrão (`runc`, `crun`, `runsc`) exigem privilégios de `root`, exposição de `/var/run/docker.sock` do host, `--privileged` (`CAP_SYS_ADMIN`) ou namespaces de usuário (`unshare(CLONE_NEWUSER)`), que ampliam a superfície de ataque do kernel do host.
- No **Windows** e no **macOS**, os mecanismos de contêiner (`Docker Desktop`, `Podman Machine`, `Lima`, `OrbStack`) inicializam um kernel completo de máquina virtual Linux dentro do WSL2, do Hyper-V ou do `Virtualization.framework`, e executam um daemon persistente em segundo plano dentro dessa VM.

**[gvx](https://github.com/gfire-sigs/gvx)** (CLI `rungv` e SDK Go `z.gfire.dev/gvx/pkg/gvx`) oferece uma **alternativa segura e de privilégio zero**. Construído como um fork rastreável a montante do kernel Linux em espaço de usuário `gVisor` do Google (`Sentry`) e da pilha de rede em espaço de usuário (`netstack`), o `gvx` executa binários `linux/amd64` e `linux/arm64` ELF64 não modificados e contêineres OCI diretamente dentro de **um único processo do host, sem privilégios e com bloqueio próprio** no Windows, no macOS e no Linux.

> **Garantia de Segurança (Defesa em Profundidade de Três Anéis)**: o `gvx` nunca enfraquece as fronteiras de segurança do SO host, nunca instala drivers de kernel e nunca exige `root`, `sudo`, `--privileged` no host ou `CLONE_NEWUSER`. Antes de executar qualquer instrução do guest, o `gvx` bloqueia o próprio processo do host usando Windows Restricted Tokens e Job Objects, Seatbelt do macOS (`deny default`) ou `PR_SET_NO_NEW_PRIVS` + `seccomp` BPF no Linux. Todas as chamadas de sistema do guest, os privilégios virtuais de `UID 0`, as montagens (`VFS2`) e as tabelas de rede (`netstack`) são estritamente confinados dentro do kernel `Sentry` em Go, seguro quanto à memória.

| Runtime                    | SO do Host                                            |        Cold Start | Consumo de Memória | Requer Admin ou `sudo` | Daemon de VM em Segundo Plano | Execução Direta de Imagem OCI |
| :------------------------- | :---------------------------------------------------- | ----------------: | -----------------: | :--------------------- | :---------------------------- | :---------------------------- |
| **`gvx` (`whpx` / `hvf`)** | Windows (`amd64`, `arm64`) e macOS (`arm64`)          |          `~20 ms` |         `~30 MiB` | Não                    | Não                           | Sim                           |
| **`gvx` (`systrap`)**      | Windows (`amd64`, `arm64`) e Linux (`amd64`, `arm64`) |    `~25 a 65 ms`  |         `~31 MiB` | Não                    | Não                           | Sim                           |
| **WSL2 / Docker Desktop**  | Windows e macOS                                       |  `800 a 2500 ms`  |       `> 512 MiB` | Sim (Configuração Inicial) | Sim                       | Requer Daemon                 |
| **QEMU (Sistema Completo)** | Windows e macOS                                      | `1500 a 4000 ms`  |       `> 256 MiB` | Não                    | Não                           | Requer Imagem de Disco        |

Nenhum kernel de VM Linux é inicializado no Windows ou no macOS. Nenhum daemon em segundo plano é executado no host. Não são necessários privilégios de `root`, `sudo`, namespaces de usuário (`CLONE_NEWUSER`), `mount(2)`, drivers `TUN`/`TAP` ou `CAP_NET_ADMIN` no SO host. Dentro desse processo sem privilégios, o `gvx` executa **Docker-in-Docker (`docker:dind`)**, `docker build`, `docker compose` e **Kubernetes de alta disponibilidade com múltiplos nós (`k3s` com `etcd` embutido e CNI `Calico`)**.

---

## Ciclo de Vida do Contêiner e Bloqueio do Host em Três Anéis

Cada sandbox do `gvx` é executado dentro de um único processo do host sem privilégios e impõe um ciclo de vida em três fases: pré-abertura de todos os descritores de arquivo e sockets necessários do host, bloqueio do processo do SO host por meio de `pkg/hostlockdown` e entrada no loop de execução `Sentry` dentro do processo.

![Ciclo de Vida do Contêiner gvx e Autobloqueio do Host](/assets/images/gvx/gvx-lifecycle-lockdown.png)

Antes de transferir o controle para a primeira instrução do guest, o `gvx` pré-abre seus descritores de camadas de imagem `.erofs` em cache, os descritores de arquivos de volume `.ext4`, o handle `*os.Root` de `/workspace` e os sockets de rede do host, e então invoca `hostlockdown.Apply()`:

1. **Windows NT (`lockdown_windows.go`)**: Chama `AdjustTokenPrivileges` com `SE_PRIVILEGE_REMOVED` para remover privilégios no próprio lugar, vincula um token de impersonação restrito `DISABLE_MAX_PRIVILEGE` com integridade Low (`S-1-16-4096`), atribui o processo a um Job Object anônimo com `JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 1` (bloqueando a criação de qualquer processo filho) e habilita `DisallowWin32kSystemCalls = 1` por meio de `SetProcessMitigationPolicy`.
2. **macOS XNU (`lockdown_darwin.go`)**: Define `RLIMIT_NPROC = 0` e aplica um perfil Seatbelt (`sandbox_init_with_parameters`) começando em `(version 1)(deny default)` que bloqueia `process-fork`, `process-exec*` e todas as novas aberturas de arquivos do host.
3. **Linux (`lockdown_linux.go` + `pkg/gvx/syscallfilter_linux.go`)**: Define `PR_SET_NO_NEW_PRIVS` e instala a allowlist `seccomp` BPF do Sentry em todas as threads (`SECCOMP_FILTER_FLAG_TSYNC`), com regras `EPERM` explícitas para `execve`, `execveat`, `clone`, `openat` e `socket`.

---

## Interceptação de Syscalls Multiplataforma e Paginação de 4 KB (`pkg/sentry/platform`)

Binários Linux ELF64 pressupõem granularidade de página de memória de 4 KB (`0x1000`) para mapeamentos de segmentos `mmap(MAP_FIXED)`. No entanto, `VirtualAlloc` e `MapViewOfFile3` do Windows impõem alinhamento de 64 KB (`0x10000`), e o macOS em Apple Silicon (`darwin/arm64`) usa páginas de host de 16 KB (`0x4000`). Além disso, cada SO exige um mecanismo diferente para interceptar instruções Linux `SYSCALL` (`amd64`) e `SVC #0` (`arm64`) sem inicializar uma VM Linux.

O `gvx` resolve ambos os problemas em quatro backends de execução que implementam `pkg/sentry/platform.Context`:

![Mecânica de Interceptação de Syscalls e Paginação de 4KB da Plataforma gvx](/assets/images/gvx/gvx-platform-syscalls.png)

### 1. Mecanismo de Hardware do Windows: `platform/whpx` (`WinHvPlatform.dll`)

Em `windows/amd64` e `windows/arm64`, o `platform/whpx` cria uma partição de hipervisor leve por meio de `WHvCreatePartition` sem inicializar um kernel de SO convidado:

- **Desacoplador de Paginação de 64 KB para 4 KB**: O `whpx` registra cada arena de 64 MiB de `pgalloc.MemoryFile` na partição uma única vez, por meio de `WHvMapGpaRange`. As chamadas subsequentes de `MapFile` e `Unmap` modificam apenas as tabelas de páginas do guest dentro da partição, impondo permissões `R/W/X` exatas de 4 KB apesar da granularidade de alocação de 64 KB do Windows.
- **Troca de Registradores Sem API via `CommPage`**:
  - Em `amd64`, um `SYSCALL` de Ring-3 do guest entra em um stub `MSR_LSTAR` de Ring-0 dentro da partição (`stubgen_x86.go`), que grava os GPRs da syscall de caminho rápido (`RAX, RDI, RSI, RDX, R10, R8, R9, RIP, RSP`) em uma `CommPage` compartilhada de 4 KB e executa `HLT` para sair de `WHvRunVirtualProcessor`.
  - Em `arm64`, um `SVC #0` de EL0 do guest entra nos vetores de EL1 (`stubgen_a64.go`), grava `X0..X8, SP_EL0, ELR_EL1, PSTATE` na `CommPage` e carrega a partir de GPA zero sem backing para acionar uma saída de memória de volta ao Sentry.

### 2. Mecanismo de Hardware do macOS: `platform/hvf` (`Hypervisor.framework`)

Em Apple Silicon (`darwin/arm64`), o `platform/hvf` executa threads de contêiner dentro de vCPUs do `Hypervisor.framework` (`hv_vm_create`, `hv_vcpu_run`):

- **Tradução de MMU de 4 KB sobre 16 KB em Dois Estágios**: O Stage-2 (`hv_vm_map`) mapeia blocos de 1 GiB do arquivo de memória para o espaço de endereços físicos intermediários (IPA) uma única vez, com granularidade de página de host de 16 KB e `HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC`. Dentro da vCPU, o stub EL1 `bluepill` (`bluepill_arm64.go`) configura `TCR_EL1.TG0 = 0b00` (granule de 4 KB) em `TTBR0_EL1` e preenche entradas de tabela de páginas Stage-1 de 4 KB com permissões exatas `R-X` ou `RW-` (`UXN=1`). Como a MMU do ARM64 impõe a interseção das permissões Stage-1 e Stage-2, o hardware captura falhas de permissão em fronteiras exatas de 4 KB.
- **Interceptação de Syscall**: O `SVC #0` de EL0 do guest é direcionado para o `VBAR_EL1` de EL1, grava os registradores na `CommPage` compartilhada de 4 KB e executa `HVC #0` para retornar de `hv_vcpu_run` à thread Go do Sentry.

### 3. Fallback em Modo Usuário do Windows: `platform/systrap` (`winsystrap`)

Quando a virtualização de hardware não está disponível (como dentro de VMs de nuvem aninhadas), o `winsystrap` executa código do guest em modo usuário em `windows/amd64` e `windows/arm64`:

- **Isolamento de `CR3` / `TTBR0_EL1` por Hardware**: Threads do guest são executadas dentro de subprocessos de stub isolados, inicializados a partir de um executável gerado de 1 KB (`stubimage_xplat.go`), confinados por um token de integridade Low e por um Job Object.
- **Patch Binário In-Place e IPC `winSysmsg`**: Em `amd64`, o patcher (`patcher_amd64_xplat.go`) substitui instruções `syscall` de 2 bytes (`0f 05`) por saltos `jmp rel32` de 5 bytes (ou armadilhas de breakpoint `CC 90` quando uma janela de 5 bytes não está disponível) para uma ilha de caminho rápido. Em `arm64`, `svc #0` é substituído por um desvio `B` para um slot da ilha. A ilha grava os registradores na página `winSysmsg` compartilhada e se sincroniza com o Sentry por meio de `WaitOnAddress` e `WakeByAddressSingle`, enquanto as armadilhas não aplicadas e as falhas de página são interrompidas em um Windows Debug Object (`WaitForDebugEventEx`).

### 4. Mecanismo em Modo Usuário do Linux: `platform/systrap`

Em `linux/amd64` e `linux/arm64`, o `systrap` executa threads do guest (`sysmsg`) que capturam syscalls do guest por meio de `SECCOMP_RET_TRAP` (`SIGSYS`) e aplicam patches binários nos pontos `syscall` para um trampolim de memória compartilhada (`sysmsg`), sincronizado via `SYS_FUTEX`. Enquanto isso, uma thread stub `syscallThread` (`syscall_thread.go`) executa operações de espaço de endereçamento (`mmap`, `munmap`, `clone`) via `SECCOMP_RET_USER_NOTIF` (`_RUN_SECCOMP_LOOP`). Quando o `gvx` é executado dentro de um sandbox `gVisor` externo (`runsc`), em que o único slot `SECCOMP_FILTER_FLAG_NEW_LISTENER` retorna `EBUSY`, o `gvx` alterna automaticamente o `syscallThread` para um loop de futex em memória compartilhada (`_RUN_SYSCALL_LOOP`), conforme detalhado na [Parte 3 desta série](/blog/posts/docker-in-docker-inside-gvisor-with-gvx-z48916d03).

---

## Como o `gvx` Mapeia Syscalls Linux do Guest para Subsistemas Virtuais e Handles do Host

Assim que um mecanismo de plataforma intercepta uma instrução `SYSCALL` (`amd64`) ou `SVC #0` (`arm64`) do guest e grava os registradores do guest na página compartilhada de 4 KB (`CommPage`, `sysmsg` ou `winSysmsg`), o controle retorna à goroutine da tarefa Go do `Sentry` (`pkg/sentry/kernel/task_syscall.go`). Em vez de encaminhar syscalls Linux para o kernel do SO host subjacente, `Task.doSyscall()` salva o estado original dos registradores (`SyscallSaveOrig()`), avalia quaisquer filtros `seccomp` BPF e paradas `ptrace` no guest e despacha o número da syscall por meio de `linux.AMD64` ou `linux.ARM64` (`pkg/sentry/syscalls/linux/linux64.go`, cobrindo cerca de 370 syscalls Linux) para quatro domínios internos:

![Como o gvx Mapeia Syscalls Linux do Guest para Subsistemas e SO Host](/assets/images/gvx/gvx-syscall-mapping.png)

| Domínio de Syscall | Syscalls Linux Representativas do Guest | Subsistema Interno do `gvx` (`pkg/sentry`) | Interação com a Fronteira do SO Host (Após `hostlockdown`) |
| :--- | :--- | :--- | :--- |
| **A. Processo, Namespace, Montagem e Sincronização** | `clone`, `execve`, `unshare`, `setns`, `mount`, `umount2`, `pivot_root`, `setuid`, `capset`, `futex`, `epoll_wait`, `pipe2` | `kernel.Task`, credenciais virtuais, tabela de futex e `VFS2` em memória (`procfs`, `sysfs`, `cgroupfs` v2, `tmpfs`, `overlayfs`) | **Zero syscalls no host** (estado Go 100% em memória; completamente invisível ao SO host) |
| **B. Memória Virtual (`MM`)** | `mmap`, `munmap`, `mremap`, `mprotect`, `brk`, `madvise`, `memfd_create` | `mm.MemoryManager` (árvore de VMA de 4 KB) e `pgalloc.MemoryFile` | Atualizações bidirecionais de tabelas de páginas de 4 KB via `WHvMapGpaRange`, `hv_vm_map` + `TTBR0_EL1` ou `mmap`/`mprotect` do stub |
| **C. Arquivos e Armazenamento (`VFS2`)** | `openat`, `pread64`, `pwrite64`, `getdents64`, `statx`, `renameat2`, `setxattr`, `mknod`, `inotify_add_watch` | Roteador da tabela de montagens de `vfs.VirtualFilesystem` (`fsimpl/erofs`, `fsimpl/ext4lite`, `fsimpl/hostfs` v2) | `pread`/`pwrite` bidirecionais em 1 FD `.erofs` fixado ou 1 FD `.ext4`, ou percursos relativos restritos em `*os.Root` |
| **D. Rede e Netfilter** | `socket`, `bind`, `listen`, `connect`, `sendmsg`, `recvmsg`, `netlink`, `setsockopt(IPT_SO_SET_REPLACE)` | `pkg/tcpip` em espaço de usuário (`lo`, `eth0`, `docker0`, `veth`, `vxlan`, `wireguard`, `ipset`, `iptables-legacy`) | O tráfego interno ao sandbox usa **zero syscalls no host**; o tráfego externo é mapeado para `net.Dial`/`net.Listen` (`-net=nat`) ou 1 socket UDP (`-net=wg`) |

Quando o handler retorna `(rval, ctrl, err)`, `Task.doSyscallInvoke()` converte qualquer erro em um `errno` Linux negativo (`-ExtractErrno(err, sysno)`), grava o valor de retorno de volta na página de registradores compartilhada (`RAX` em `amd64`, `X0` em `arm64`) e retoma a execução do guest.

---

## Armazenamento (`VFS2`) e Rede em Espaço de Usuário com Trilha Dupla (`netstack`)

Todas as operações de arquivo e de rede do guest são atendidas dentro do `Sentry` em Go por meio de três sistemas de arquivos `VFS2` e duas trilhas de `pkg/netbackend`:

![Mecanismos de Armazenamento VFS2 do gvx e Netstack de Trilha Dupla](/assets/images/gvx/gvx-storage-netstack.png)

| Mecanismo de Armazenamento | Papel de Montagem no `gvx` | Recurso de Host Subjacente | Chamadas `openat` / `NtCreateFile` no Host em Tempo de Execução | Varreduras por Arquivo do Windows Defender (`WdFilter.sys`) |
| :--- | :--- | :--- | ---: | ---: |
| **`fsimpl/erofs`** | Camadas inferiores somente leitura de imagens OCI | Um único arquivo `<sha256>.erofs` por camada | `0` | `0` |
| **`fsimpl/ext4lite`** | Volumes nomeados (`-v name:/path`) | Um único arquivo `<name>.ext4` por volume | `0` | `0` |
| **`fsimpl/hostfs` v2** | Workspace do host (`-workspace`, `-v /host:/guest`) | Diretório do host fixado em `*os.Root` | `O(profundidade)` por abertura sem cache | `1` por fechamento de arquivo do host |

### Por que o `ext4lite` É Importante para Docker, Bancos de Dados e Gerenciadores de Pacotes

Extrair ou gravar dezenas de milhares de arquivos de contêineres diretamente em NTFS do Windows ou APFS do macOS aciona varreduras de minifiltros antivírus (`WdFilter.sys`), colisões de sensibilidade a maiúsculas e minúsculas e ausência de atributos estendidos POSIX.

`pkg/sentry/fsimpl/ext4lite` implementa um sistema de arquivos `ext4` escrito em Go puro dentro de um único arquivo do host pré-aberto (`%LOCALAPPDATA%\gvx\cache\volumes\<name>.ext4` no Windows, `~/Library/Caches/gvx/volumes/<name>.ext4` no macOS ou `~/.cache/gvx/volumes/<name>.ext4` no Linux), com:

- **Blocos de 4 KiB e grupos de blocos dinâmicos de 16 MiB (`meta_bg`)**: Cresce dinamicamente sem paradas de alocação de arquivos esparsos (`fallocate` no Linux, `fcntl(F_PREALLOCATE)` no macOS, `FileAllocationInfo` no Windows) e compacta grupos finais não utilizados na desmontagem limpa.
- **Journal JBD2 em modo ordenado (inode 8)**: Confirmações atômicas de transações com somas de verificação CRC-32 e blocos de revogação, além da recuperação via `fsckLite`.
- **Suporte à camada superior do `overlayfs`**: Implementa os atributos estendidos `trusted.overlay.*` e `security.capability`, whiteouts de dispositivos de caractere (`0:0`), relatório de entradas de diretório `d_type` e `RENAME_EXCHANGE`.

---

## Cargas de Trabalho Práticas: Docker Engine, Kubernetes (`k3s` + `Calico`) e SDK Go

### Instalando o `rungv`: Versões Pré-compiladas com Atestação SLSA ou `go install`

Você pode baixar um arquivo `rungv` pré-compilado para `linux/amd64`, `linux/arm64`, `darwin/arm64`, `windows/amd64` ou `windows/arm64` em [GitHub Releases](https://github.com/gfire-sigs/gvx/releases) (cada um construído pelo pipeline de release SLSA com um pacote de procedência Sigstore e `SHA256SUMS`), ou instalar diretamente a partir do código-fonte com `go install`:

```sh
# Opção A: Baixe uma versão pré-compilada e verifique a procedência de build SLSA
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

# Opção B: Instale diretamente via Go (Linux / Windows)
CGO_ENABLED=0 go install z.gfire.dev/gvx/cmd/rungv@latest
```

> No macOS (`darwin/arm64`), o arquivo de release pré-compilado já está assinado com a permissão `com.apple.security.hypervisor` (`xattr -d com.apple.quarantine rungv` remove a quarentena do navegador). Se você compilar localmente com `go install` ou `go build` no macOS, assine o binário com `codesign --sign - --entitlements entitlements.plist --force $(which rungv)`.

### 1. Executando um Docker Engine Sem Privilégios (`docker:dind`)

Seguindo [`docs/docker-engine.md`](https://github.com/gfire-sigs/gvx/blob/main/docs/docker-engine.md), você pode executar um contêiner `docker:dind` não modificado dentro do `rungv` no Windows, no macOS ou no Linux e controlá-lo com a CLI `docker` do seu host:

```sh
# 1. Crie o diretório do host para o socket Unix encaminhado
mkdir -p ~/.gvx

# 2. Inicie o docker:dind dentro de um sandbox do gvx com um volume ext4lite
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
```

Em um segundo terminal, aponte a CLI `docker` do seu host para o socket do sandbox:

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

docker info --format '{{.Driver}} {{.OperatingSystem}}'
# Saída: overlayfs Alpine Linux ... (containerized)

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

### 2. Executando Kubernetes (`k3s` + `Calico`) em Sandboxes Sem Privilégios

Como o `gvx` implementa `/dev/kmsg`, `cgroup` v2 (o OOM killer de `memory.max` e a limitação de largura de banda de `cpu.max`), `/proc/diskstats`, dispositivos netlink `wireguard` e `vxlan`, `ipset` e `iptables-legacy` (`addrtype`, `conntrack`, `statistic`, `recent`), uma imagem `rancher/k3s` não modificada alcança `Ready` dentro de um único processo `rungv`:

```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
```

Você também pode unir vários nós `gvx` por meio do WireGuard (`flannel-backend=wireguard-native` ou uma malha `wg0`), com alta disponibilidade do `etcd` embutido, ou executar o **Calico** (`calico-vxlan.yaml` com `FELIX_IPTABLESBACKEND=Legacy`) para impor `NetworkPolicy` do Kubernetes inteiramente em espaço de usuário.

### 3. Incorporando Contêineres Linux em Go via `z.gfire.dev/gvx/pkg/gvx`

Aplicações Go podem incorporar contêineres Linux diretamente, sem um daemon de contêiner externo:

```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)
}
```

---

## Leituras Adicionais Nesta Série

1. **[gvx: Executando Contêineres Linux, Docker e Kubernetes em Um Único Processo Sem Privilégios](/blog/posts/gvx-cross-platform-linux-containers-z48916d01)** (este post)
2. **[Executando Docker, docker build e docker compose Sem Root ou Namespaces de Usuário](/blog/posts/run-docker-without-root-or-userns-gvx-z48916d02)**: Como inicializar o `docker:dind` em sandboxes bloqueados nos quais `sudo`, `unshare(CLONE_NEWUSER)`, `mount(2)` e `/dev/fuse` são bloqueados.
3. **[Executando Docker-in-Docker Dentro do gVisor e de Sandboxes Aninhados com o gvx](/blog/posts/docker-in-docker-inside-gvisor-with-gvx-z48916d03)**: Por que `apt-get install docker.io` e o `runsc` aninhado falham dentro do `gVisor` por causa de cinco barreiras no kernel, e como o `gvx` executa o `docker:dind` aninhado usando um loop de futex em memória compartilhada.
4. **[Ambientes Docker Isolados e Rápidos para Rollouts de RL de Agentes de IA com o gvx](/blog/posts/fast-docker-environments-for-agent-rl-rollouts-z48916d04)**: Escalonamento de `SWE-bench` e de rollouts de aprendizado por reforço de agentes com centenas de instâncias paralelas de `docker:dind` sem privilégios e redefinições de volumes `.ext4` com copy-on-write de 100 milissegundos.
