---
id: e62d78ef5850c982dbddc9d3ff9134ae
author: Lemon Mint
title: 'gvx: Изпълнение на Linux Containers, Docker и Kubernetes в един непривилегирован процес'
description: Техническо обобщение на gvx, сигурно усилена, кросплатформена среда за изпълнение на контейнери и Go SDK, изградени върху потребителското ядро gVisor, което безопасно изпълнява Linux контейнери, Docker-in-Docker и многовъзлов高 HA Kubernetes в един непривилегирован процес в Windows, macOS и Linux.
language: bg
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
---

## Въведение: контейнери със засилена сигурност без root и без хост демони

Изпълнението на Linux контейнери, `docker build` или Kubernetes на компютър за разработка, CI рънър или мултитенантен облачен възел обикновено налага неудобен компромис със сигурността:

- На **Linux** стандартните OCI рантайми (`runc`, `crun`, `runsc`) изискват или привилегии `root`, или излагане на host `/var/run/docker.sock`, или `--privileged` (`CAP_SYS_ADMIN`), или user namespaces (`unshare(CLONE_NEWUSER)`), които разширяват повърхността на атака на хост ядрото.
- На **Windows** и **macOS** контейнерните движещи (`Docker Desktop`, `Podman Machine`, `Lima`, `OrbStack`) стартират пълно Linux ядро на виртуална машина в WSL2, Hyper-V или `Virtualization.framework` и изпълняват постоянен фонов демон във вътрешността на тази VM.

**[gvx](https://github.com/gfire-sigs/gvx)** (CLI `rungv` и Go SDK `z.gfire.dev/gvx/pkg/gvx`) предоставя **сигурна алтернатива без привилегии**. Изградена като проследима спрямо горния поток форк на user-space Linux ядрото `Sentry` и user-space мрежовия стек `netstack` на Google **gVisor**, `gvx` изпълнява непроменени `linux/amd64` и `linux/arm64` ELF64 двоични файлове и OCI контейнери директно в **един непривилегирован, самозаключващ се хост процес** на Windows, macOS и Linux.

> **Гаранция за сигурност (триетажна защита в дълбочина)**: `gvx` никога не отслабва границите на сигурност на хост операционната система, никога не инсталира драйвери на ядрото и никога не изисква `root`, `sudo`, `--privileged` на хоста или `CLONE_NEWUSER`. Преди да изпълни и една инструкция на гост системата, `gvx` заключва собствения си хост процес чрез Windows Restricted Tokens и Job Objects, macOS Seatbelt (`deny default`) или Linux `PR_SET_NO_NEW_PRIVS` и BPF `seccomp`. Всички системни извиквания на гост системата, виртуалните привилегии `UID 0`, монтиранията (`VFS2`) и мрежовите таблици (`netstack`) са строго ограничени във вътрешността на безопасното по отношение на паметта Go ядро `Sentry`.

| Рантайм                    | Хост ОС                                               |        Студен старт | Отпечатък в паметта | Нужни права на администратор или `sudo` | Фонов VM демон | Директно изпълнение на OCI образ |
| :------------------------- | :---------------------------------------------------- | ------------------: | ------------------: | :-------------------------------------- | :------------- | :------------------------------- |
| **`gvx` (`whpx` / `hvf`)** | Windows (`amd64`, `arm64`) и macOS (`arm64`)          |           `~20 ms` |         `~30 MiB` | Не                                      | Не             | Да                               |
| **`gvx` (`systrap`)**      | Windows (`amd64`, `arm64`) и Linux (`amd64`, `arm64`) |     `~25 до 65 ms` |         `~31 MiB` | Не                                      | Не             | Да                               |
| **WSL2 / Docker Desktop**  | Windows и macOS                                       |  `800 до 2500 ms` |       `> 512 MiB` | Да (първоначална настройка)             | Да             | Изисква демон                    |
| **QEMU (Full System)**     | Windows и macOS                                       | `1500 до 4000 ms` |       `> 256 MiB` | Не                                      | Не             | Изисква дисков образ             |

На Windows и macOS не се зарежда Linux ядро на VM. На хоста не работи фонов демон. На хостовата операционна система не се изискват `root`, `sudo`, user namespaces (`CLONE_NEWUSER`), `mount(2)`, драйвери `TUN`/`TAP` или привилегии `CAP_NET_ADMIN`. Във вътрешността на този непривилегирован процес `gvx` изпълнява **Docker-in-Docker (`docker:dind`)**, `docker build`, `docker compose` и **многовъзлов High-Availability Kubernetes (`k3s` с вграден `etcd` и `Calico` CNI)**.

---

## Жизнен цикъл на контейнера и триетажно хост заключване

Всяка sandbox среда на `gvx` работи във вътрешността на един непривилегирован хост процес и спазва тристепенен жизнен цикъл: предварително отваряне на всички необходими хост файлови дескриптори и сокети, заключване на хост процеса на операционната система чрез `pkg/hostlockdown` и влизане в цикъла за изпълнение на `Sentry` във вътрешността на процеса.

![Жизнен цикъл на gvx контейнер и самозаключване на хоста](/assets/images/gvx/gvx-lifecycle-lockdown.png)

Преди да предаде управлението на първата инструкция на гост системата, `gvx` предварително отваря своите кеширани дескриптори на `.erofs` слоеве на образа, дескриптори на `.ext4` томове, манипулатора `*os.Root` за `/workspace` и хост мрежовите сокети, след което извиква `hostlockdown.Apply()`:

1. **Windows NT (`lockdown_windows.go`)**: Извиква `AdjustTokenPrivileges` с `SE_PRIVILEGE_REMOVED`, за да премахне привилегиите на място, свързва ограничен токен за имперсонация `DISABLE_MAX_PRIVILEGE` с Low интегритет (`S-1-16-4096`), присвоява процеса към анонимен Job Object с `JOB_OBJECT_LIMIT_ACTIVE_PROCESS = 1` (блокиращ създаването на всякакви дъщерни процеси) и активира `DisallowWin32kSystemCalls = 1` чрез `SetProcessMitigationPolicy`.
2. **macOS XNU (`lockdown_darwin.go`)**: Задава `RLIMIT_NPROC = 0` и прилага профил на Seatbelt (`sandbox_init_with_parameters`), започващ от `(version 1)(deny default)`, който блокира `process-fork`, `process-exec*` и всички нови отваряния на хост файлове.
3. **Linux (`lockdown_linux.go` + `pkg/gvx/syscallfilter_linux.go`)**: Задава `PR_SET_NO_NEW_PRIVS` и инсталира позволения списък на BPF `seccomp` на Sentry за всички нишки (`SECCOMP_FILTER_FLAG_TSYNC`), с изрични правила `EPERM` за `execve`, `execveat`, `clone`, `openat` и `socket`.

---

## Прихващане на системни извиквания между платформи и странициране от 4 KB (`pkg/sentry/platform`)

Linux ELF64 двоичните файлове предполагат гранулярност на страниците в паметта от 4 KB (`0x1000`) за сегментни съпоставяния с `mmap(MAP_FIXED)`. Въпреки това Windows `VirtualAlloc` и `MapViewOfFile3` налагат подравняване от 64 KB (`0x10000`), а Apple Silicon macOS (`darwin/arm64`) използва хостови страници от 16 KB (`0x4000`). Освен това всяка операционна система изисква различен механизъм за прихващане на инструкциите Linux `SYSCALL` (`amd64`) и `SVC #0` (`arm64`) без стартиране на Linux VM.

`gvx` решава и двата проблема чрез четири бекенда за изпълнение, които реализират `pkg/sentry/platform.Context`:

![Механика на прихващане на системни извиквания и странициране от 4KB в gvx платформата](/assets/images/gvx/gvx-platform-syscalls.png)

### 1. Хардуерен двигател за Windows: `platform/whpx` (`WinHvPlatform.dll`)

На `windows/amd64` и `windows/arm64` `platform/whpx` създава лек хипервайзър дял чрез `WHvCreatePartition`, без да стартира ядро на гост операционна система:

- **Разделител 64 KB към 4 KB страници**: `whpx` регистрира всяка 64 MiB арена на `pgalloc.MemoryFile` при дяла еднократно чрез `WHvMapGpaRange`. Последващите извиквания на `MapFile` и `Unmap` променят само таблиците със страници на гост системата във вътрешността на дяла, налагайки точни права `R/W/X` върху страници от 4 KB, въпреки гранулярността на разпределение от 64 KB на Windows.
- **Обмен на регистри без API чрез `CommPage`**:
  - На `amd64` `SYSCALL` от гост Ring-3 влиза във вътрешен Ring-0 стъб `MSR_LSTAR` (`stubgen_x86.go`), който записва GPR регистрите на бързия път за системни извиквания (`RAX, RDI, RSI, RDX, R10, R8, R9, RIP, RSP`) в споделената `CommPage` от 4 KB и изпълнява `HLT`, за да излезе от `WHvRunVirtualProcessor`.
  - На `arm64` `SVC #0` от гост EL0 влиза във векторите на EL1 (`stubgen_a64.go`), записва `X0..X8, SP_EL0, ELR_EL1, PSTATE` в `CommPage` и зарежда от незаделен GPA нула, за да предизвика паметно излизане обратно към Sentry.

### 2. Хардуерен двигател за macOS: `platform/hvf` (`Hypervisor.framework`)

На Apple Silicon (`darwin/arm64`) `platform/hvf` изпълнява нишките на контейнерите във vCPU на `Hypervisor.framework` (`hv_vm_create`, `hv_vcpu_run`):

- **Двустепенен MMU превод от 4 KB върху 16 KB**: Stage-2 (`hv_vm_map`) съпоставя фрагменти от памет-файла по 1 GiB в пространството на междинните физически адреси (IPA) еднократно с гранулярност на хостовите страници от 16 KB, с `HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC`. Във вътрешността на vCPU стъбът EL1 `bluepill` (`bluepill_arm64.go`) конфигурира `TCR_EL1.TG0 = 0b00` (гранула от 4 KB) в `TTBR0_EL1` и попълва записите на таблиците със страници Stage-1 от 4 KB с точни права `R-X` или `RW-` (`UXN=1`). Тъй като ARM64 MMU налага сечението на правата на Stage-1 и Stage-2, хардуерът улавя грешките при права на точни граници от 4 KB.
- **Прихващане на системни извиквания**: `SVC #0` от гост EL0 преминава към EL1 `VBAR_EL1`, записва регистрите в споделената `CommPage` от 4 KB и изпълнява `HVC #0`, за да се върне от `hv_vcpu_run` към нишката на Go Sentry.

### 3. Резервен потребителски режим за Windows: `platform/systrap` (`winsystrap`)

Когато хардуерната виртуализация не е налице (например във вложени облачни VM), `winsystrap` изпълнява гост код в потребителски режим на `windows/amd64` и `windows/arm64`:

- **Хардуерна изолация чрез `CR3` / `TTBR0_EL1`**: Нишките на гост системата работят във вътрешността на изолирани подпроцеси стъбове, стартирани от генерирано изпълнимо изображение от 1 KB (`stubimage_xplat.go`), ограничено от токен с Low интегритет и Job Object.
- **Патчване на двоичния код на място и IPC `winSysmsg`**: На `amd64` патчерът (`patcher_amd64_xplat.go`) заменя 2-байтовите инструкции `syscall` (`0f 05`) с 5-байтови скокове `jmp rel32` (или с капани `CC 90`, когато 5-байтов прозорец не е наличен) към остров за бърз път. На `arm64` `svc #0` се патчва с клон `B` към слот в острова. Островът записва регистрите в споделената страница `winSysmsg` и се синхронизира със Sentry чрез `WaitOnAddress` и `WakeByAddressSingle`, докато непатчнатите капани и грешките на страници спират при Windows Debug Object (`WaitForDebugEventEx`).

### 4. Двигател за Linux в потребителски режим: `platform/systrap`

На `linux/amd64` и `linux/arm64` `systrap` изпълнява нишки на гост системата (`sysmsg`), които прихващат системните извиквания на гост системата чрез `SECCOMP_RET_TRAP` (`SIGSYS`) и двоично патчват местата `syscall` в трамплин в споделена памет (`sysmsg`), синхронизиран чрез `SYS_FUTEX`. Междувременно стъбовата нишка `syscallThread` (`syscall_thread.go`) изпълнява операции по адресното пространство (`mmap`, `munmap`, `clone`) чрез `SECCOMP_RET_USER_NOTIF` (`_RUN_SECCOMP_LOOP`). Когато `gvx` работи във вътрешността на външна `gVisor` (`runsc`) среда, в която единственият слот `SECCOMP_FILTER_FLAG_NEW_LISTENER` връща `EBUSY`, `gvx` автоматично превключва `syscallThread` към цикъл с futex в споделена памет (`_RUN_SYSCALL_LOOP`), както е описано в [част 3 от тази серия](/blog/posts/docker-in-docker-inside-gvisor-with-gvx-z48916d03).

---

## Как `gvx` съпоставя системните извиквания на гост Linux с виртуални подсистеми и хостови манипулатори

След като платформеният двигател прихване инструкцията `SYSCALL` (`amd64`) или `SVC #0` (`arm64`) на гост системата и запише регистрите на гост системата в страницата от 4 KB (`CommPage`, `sysmsg` или `winSysmsg`), управлението се връща към горутината на задачата на Go `Sentry` (`pkg/sentry/kernel/task_syscall.go`). Вместо да препраща системните извиквания на Linux към ядрото на основната хостова операционна система, `Task.doSyscall()` запазва първоначалното състояние на регистрите (`SyscallSaveOrig()`), оценява всички вътрешни за гост системата BPF филтри `seccomp` и спирания `ptrace` и изпраща номера на системното извикване през `linux.AMD64` или `linux.ARM64` (`pkg/sentry/syscalls/linux/linux64.go`, обхващащ ~370 системни извиквания на Linux) към четири вътрешни домейна:

![Как gvx съпоставя системните извиквания на гост Linux с подсистеми и хостовата ОС](/assets/images/gvx/gvx-syscall-mapping.png)

| Домейн на системни извиквания | Представителни системни извиквания на гост Linux | Вътрешна подсистема на `gvx` (`pkg/sentry`) | Взаимодействие с границата на хостовата ОС (след `hostlockdown`) |
| :--- | :--- | :--- | :--- |
| **A. Процеси, namespace, монтиране и синхронизация** | `clone`, `execve`, `unshare`, `setns`, `mount`, `umount2`, `pivot_root`, `setuid`, `capset`, `futex`, `epoll_wait`, `pipe2` | `kernel.Task`, виртуални идентификационни данни, таблица futex и `VFS2` в паметта (`procfs`, `sysfs`, `cgroupfs` v2, `tmpfs`, `overlayfs`) | **Нула хостови системни извиквания** (100% състояние в паметта на Go; напълно невидимо за хостовата ОС) |
| **B. Виртуална памет (`MM`)** | `mmap`, `munmap`, `mremap`, `mprotect`, `brk`, `madvise`, `memfd_create` | `mm.MemoryManager` (дърво на VMA от 4 KB) и `pgalloc.MemoryFile` | Двупосочни обновявания на таблиците със страници от 4 KB чрез `WHvMapGpaRange`, `hv_vm_map` + `TTBR0_EL1` или стъбови `mmap`/`mprotect` |
| **C. Файлове и съхранение (`VFS2`)** | `openat`, `pread64`, `pwrite64`, `getdents64`, `statx`, `renameat2`, `setxattr`, `mknod`, `inotify_add_watch` | Маршрутизатор на таблицата с монтирания `vfs.VirtualFilesystem` (`fsimpl/erofs`, `fsimpl/ext4lite`, `fsimpl/hostfs` v2) | Двупосочни `pread`/`pwrite` към 1 закачен FD на `.erofs` или 1 FD на `.ext4`, или ограничени относителни обхождания върху `*os.Root` |
| **D. Мрежа и Netfilter** | `socket`, `bind`, `listen`, `connect`, `sendmsg`, `recvmsg`, `netlink`, `setsockopt(IPT_SO_SET_REPLACE)` | Потребителско пространство `pkg/tcpip` (`lo`, `eth0`, `docker0`, `veth`, `vxlan`, `wireguard`, `ipset`, `iptables-legacy`) | Трафикът във вътрешността на sandbox среда използва **нула хостови системни извиквания**; външният трафик се съпоставя с `net.Dial`/`net.Listen` (`-net=nat`) или с 1 UDP сокет (`-net=wg`) |

Когато обработчикът върне `(rval, ctrl, err)`, `Task.doSyscallInvoke()` превръща всяка грешка в отрицателен Linux `errno` (`-ExtractErrno(err, sysno)`), записва върнатата стойност обратно в споделената страница с регистри (`RAX` на `amd64`, `X0` на `arm64`) и възобновява изпълнението на гост системата.

---

## Съхранение (`VFS2`) и двупътна мрежа в потребителско пространство (`netstack`)

Всички файлови и мрежови операции на гост системата се обслужват във вътрешността на Go `Sentry` чрез три файлови системи `VFS2` и два трака `pkg/netbackend`:

![Двигатели за съхранение VFS2 и двупътен netstack в gvx](/assets/images/gvx/gvx-storage-netstack.png)

| Двигател за съхранение | Роля на монтиране в `gvx` | Хостов ресурс зад него | Извиквания `openat` / `NtCreateFile` към хоста при изпълнение | Сканирания на файлове от Windows Defender (`WdFilter.sys`) |
| :--------------------- | :----------------------------------------------- | :------------------------------------- | -----------------------------------------------: | -----------------------------------------------: |
| **`fsimpl/erofs`**     | Долни слоеве на OCI образ, само за четене        | Един файл `<sha256>.erofs` на слой     |                                              `0` |                                              `0` |
| **`fsimpl/ext4lite`**  | Именувани томове (`-v name:/path`)               | Един файл `<name>.ext4` на том         |                                              `0` |                                              `0` |
| **`fsimpl/hostfs` v2** | Работно пространство на хоста (`-workspace`, `-v /host:/guest`) | Закачена хостова директория `*os.Root` |                     `O(depth)` при всяко некеширано отваряне |                          `1` при всяко затваряне на хостов файл |

### Защо `ext4lite` е важен за Docker, бази данни и мениджъри на пакети

Извличането или записването на десетки хиляди файлове на контейнери директно върху Windows NTFS или macOS APFS предизвиква сканиране от антивирусния minifilter (`WdFilter.sys`), конфликти при чувствителност към регистър на имената и липсващи разширени атрибути на POSIX.

`pkg/sentry/fsimpl/ext4lite` реализира чиста Go файлова система `ext4` във вътрешността на един предварително отворен хостов файл (`%LOCALAPPDATA%\gvx\cache\volumes\<name>.ext4` на Windows, `~/Library/Caches/gvx/volumes/<name>.ext4` на macOS или `~/.cache/gvx/volumes/<name>.ext4` на Linux) със следните характеристики:

- **Блокове от 4 KiB и динамични блокови групи от 16 MiB (`meta_bg`)**: Расте динамично, без забавяния при разпределяне на разредени файлове (`fallocate` на Linux, `fcntl(F_PREALLOCATE)` на macOS, `FileAllocationInfo` на Windows), и уплътнява неизползваните крайни групи при чисто размонтиране.
- **Журнал JBD2 в ordered режим (inode 8)**: Атомарно потвърждаване на транзакции с контролни суми CRC-32 и revoke блокове, плюс възстановяване чрез `fsckLite`.
- **Поддръжка на горния слой на `overlayfs`**: Реализира разширените атрибути `trusted.overlay.*` и `security.capability`, символни whiteout устройства (`0:0`), отчитане на записи в директории `d_type` и `RENAME_EXCHANGE`.

---

## Практически натоварвания: Docker Engine, Kubernetes (`k3s` + `Calico`) и Go SDK

### Инсталиране на `rungv`: предварително компилирани издания с SLSA атестация или `go install`

Можете да изтеглите предварително компилиран архив `rungv` за `linux/amd64`, `linux/arm64`, `darwin/arm64`, `windows/amd64` или `windows/arm64` от [GitHub Releases](https://github.com/gfire-sigs/gvx/releases) (всеки от които е изграден от конвейера за издания SLSA с пакет за произход Sigstore и `SHA256SUMS`), или да инсталирате директно от изходния код с `go install`:

```sh
# Вариант A: Изтеглете предварително компилирано издание и проверете 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

# Вариант B: Инсталирайте директно чрез Go (Linux / Windows)
CGO_ENABLED=0 go install z.gfire.dev/gvx/cmd/rungv@latest
```

> На macOS (`darwin/arm64`) предварително компилираният архив на изданието вече е подписан с правото `com.apple.security.hypervisor` (`xattr -d com.apple.quarantine rungv` премахва карантината на браузъра). Ако компилирате локално с `go install` или `go build` на macOS, подпишете двоичния файл с `codesign --sign - --entitlements entitlements.plist --force $(which rungv)`.

### 1. Стартиране на непривилегирован Docker Engine (`docker:dind`)

Според [`docs/docker-engine.md`](https://github.com/gfire-sigs/gvx/blob/main/docs/docker-engine.md) можете да стартирате непроменен контейнер `docker:dind` в `rungv` на Windows, macOS или Linux и да го управлявате със своя хостов CLI `docker`:

```sh
# 1. Създайте хостовата директория за пренасочения Unix сокет
mkdir -p ~/.gvx

# 2. Стартирайте docker:dind в sandbox среда на gvx с том 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
```

Във втори терминал насочете своя хостов CLI `docker` към сокета на sandbox средата:

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

docker info --format '{{.Driver}} {{.OperatingSystem}}'
# Изход: overlayfs Alpine Linux ... (containerized)

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

### 2. Стартиране на Kubernetes (`k3s` + `Calico`) в непривилегировани sandbox среди

Тъй като `gvx` реализира `/dev/kmsg`, `cgroup` v2 (убиецът на OOM `memory.max` и ограничаването на честотната лента `cpu.max`), `/proc/diskstats`, мрежовите устройства `wireguard` и `vxlan` netlink, `ipset` и `iptables-legacy` (`addrtype`, `conntrack`, `statistic`, `recent`), непроменен образ `rancher/k3s` достига състояние `Ready` във вътрешността на един процес `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
```

Можете също да свържете няколко възела `gvx` през WireGuard (`flannel-backend=wireguard-native` или мрежа `wg0`) с вграден `etcd` и висока наличност, или да стартирате **Calico** (`calico-vxlan.yaml` с `FELIX_IPTABLESBACKEND=Legacy`), за да наложите Kubernetes `NetworkPolicy` изцяло в потребителското пространство.

### 3. Вграждане на Linux контейнери в Go чрез `z.gfire.dev/gvx/pkg/gvx`

Go приложенията могат да вграждат Linux контейнери директно, без външен демон за контейнери:

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

---

## Допълнително четиво в тази серия

1. **[gvx: Изпълнение на Linux контейнери, Docker и Kubernetes в един непривилегирован процес](/blog/posts/gvx-cross-platform-linux-containers-z48916d01)** (тази публикация)
2. **[Изпълнение на Docker, docker build и docker compose без root или User Namespaces](/blog/posts/run-docker-without-root-or-userns-gvx-z48916d02)**: Как да стартирате `docker:dind` в заключени sandbox среди, където `sudo`, `unshare(CLONE_NEWUSER)`, `mount(2)` и `/dev/fuse` са блокирани.
3. **[Изпълнение на Docker-in-Docker във вътрешността на gVisor и вложени sandbox среди с gvx](/blog/posts/docker-in-docker-inside-gvisor-with-gvx-z48916d03)**: Защо `apt-get install docker.io` и вложеният `runsc` се провалят във вътрешността на `gVisor` през пет бариери на ядрото и как `gvx` изпълнява вложен `docker:dind` чрез цикъл с futex в споделена памет.
4. **[Бързи изолирани Docker среди за RL rollouts на AI агенти с gvx](/blog/posts/fast-docker-environments-for-agent-rl-rollouts-z48916d04)**: Мащабиране на `SWE-bench` и rollouts за обучение на агенти с подкрепление със стотици паралелни непривилегировани инстанции на `docker:dind` и 100-милисекундни копия при запис (copy-on-write) на `.ext4` томове.
