---
id: 517bf76b20da9b1bac643f4bac1bfd6b
author: Lemon Mint
title: Gyors, izolált Docker-környezetek AI-ügynökök RL-kigördítéseihez a gvx segítségével
description: Hogyan futtassunk biztonságosan több százas számú, párhuzamos, erősen izolált, jogosultság nélküli Docker- és Kubernetes-környezetet SWE-bench és kódoló ágens megerősítéses tanulási rollout-jaihoz, 100 milliszekundumos, másolás-íráskor (copy-on-write) működő ext4lite kötetvisszaállításokkal?
language: hu
date: 2026-11-06T12:02:55.95126412Z
path: /blog/posts/fast-docker-environments-for-agent-rl-rollouts-z48916d04
go_package: z.gfire.dev/gvx
go_repourl: https://github.com/gfire-sigs/gvx.git
category: ai
---

## A biztonsági és infrastruktúrás szűk keresztmetszet a Coding Agent RL rollout-okban

A szoftvermérnöki ágensek képzése és értékelése olyan benchmarkokon és megerősítéses tanulási (RL) keretrendszereken, mint a **SWE-bench**, **SWE-ReX**, **R2E-Gym**, **SWE-Gym**, **Verl** és **OpenHands**, több ezer párhuzamos rollout végrehajtását igényli nem megbízható, LLM által generált kódon. Valós szoftverfejlesztési feladatokban az ágens nem csupán szövegfájlokat szerkeszt: lefuttatja a `docker build` parancsot, adatbázisokat és mikroszolgáltatásokat indít `docker compose` segítségével, integrációs tesztcsomagokat hajt végre, és konténernaplókat vizsgál.

Rollout-méretben (klaszterenként 128 és 1024 egyidejű epizód között) a meglévő konténerinfrastruktúra négy rendszerszintű biztonsági és teljesítménybeli szűk keresztmetszetbe ütközik:

1. **Gazdagépi `dockerd` zárolási versengés és állapotszivárgás**: Több száz egyidejű RL-munkafolyamat egyetlen gazdagépi `/var/run/docker.sock` socketre irányítása minden ágensnek root-egyenértékű hozzáférést ad a gazdagépi daemonhoz, sorosítja az image-rétegek kicsomagolását, kimeríti a `docker0` alhálózati címkiosztásait, a `Another app is currently holding the xtables lock` hibákat idézi elő a gazdagépi `iptables`-ben, és epizódok között árva konténereket szivárogtat.
2. **Privilegizált DinD konténer-kiszökési kockázat**: A szabványos `docker:dind` konténerek futtatásához `--privileged` (`CAP_SYS_ADMIN`) szükséges, ami nyers gazdagépi blokkeszközöket, cgroup release agenteket és kernelmodulokat tesz elérhetővé a megbízhatatlan RL-rollout-ok számára.
3. **Hardveres virtualizáció (`/dev/kvm`) korlátai**: A MicroVM futtatókörnyezetek (`Firecracker`, `QEMU`, `Kata Containers`) tisztán izolálják a belső kerneleket, de `/dev/kvm` eszközt igényelnek. A beágyazott virtualizáció nélküli szabványos Kubernetes podok, a KVM-et letiltott bare-metal felhőpéldányok és a meglévő `gVisor` (`runsc`) sandboxok nem tudnak KVM microVM-eket indítani.
4. **Lassú epizódvisszaállítás (`env.reset()`) késleltetése**: Egy friss `docker:dind` környezet indítása, valamint az alapimage-ek letöltése vagy kicsomagolása minden RL-epizódhoz 10 és 60 másodperc közötti időt vesz igénybe, miközben a GPU-s tanítómunkafolyamatok tétlenül várnak a környezetek visszaállítására.

**[gvx](https://github.com/gfire-sigs/gvx)** (`rungv` CLI és `z.gfire.dev/gvx/pkg/gvx` Go SDK) egy **biztonságos, védelmi rétegzésen alapuló rollout futtatókörnyezetet** biztosít, amely mind a négy szűk keresztmetszetet megoldja. Minden rollout-környezet egyetlen **privilégiumok nélküli, önzárolt felhasználói térbeli folyamatként** fut (amelyet Google gVisor `Sentry` kernele, a `pkg/hostlockdown` csomag és egy memóriabeli `netstack` izolál), és teljes `/var/lib/docker` állapota egyetlen **másolás-íráskor (copy-on-write) `.ext4` fájlban (`ext4lite`)** található.

> **Nulla-privilégiumú biztonság megbízhatatlan ágensrolloutokhoz**: Minden `gvx` epizód zárolja saját gazdagépi OS-folyamatát, mielőtt vendégkódot futtatna (`PR_SET_NO_NEW_PRIVS` + BPF `seccomp` Linuxon, Seatbelt `deny default` macOS-en, Restricted Token + Job Object Windows-on). Még ha egy RL-ágens az epizódján belül `docker run --privileged` vagy destruktív `rm -rf /` parancsot hajt végre, ezek a műveletek szigorúan az adott epizód felhasználói térbeli `Sentry` kernelén és átmeneti `.ext4` kötetfájlján belül maradnak.

---

## Rollout-architektúra: párhuzamos nem privilegizált példányok + reflink pillanatképek

A `gvx`-ben minden rollout-munkafolyamat egy közönséges, nem privilegizált OS-folyamat, saját gVisor `Sentry` kernellel, saját felhasználói térbeli `netstack` hálózattal (`10.0.2.15/24`) és saját `ext4lite` blokkkötettel (`ep-N.ext4`), miközben egy csak olvasható, tartalomcímzett `erofs` OCI image-gyorsítótárat oszt meg a gazdagép lapgyorsítótárán keresztül.

![Párhuzamos Agent RL Rollout architektúra a gvx-szel](/assets/images/gvx/gvx-rl-rollout-snapshot.png)

### Miért változtatja meg az egyfájlos `ext4lite` kötet az RL-visszaállítás gazdaságtanát

Mivel a `gvx` `ext4lite` fájlrendszere egy teljes, JBD2 naplózott `ext4` kötetet (beleértve a Docker `overlayfs` rétegkönyvtárait, a `trusted.overlay.*` kiterjesztett attribútumokat, whiteout eszközcsomópontokat és image-metaadatokat) egyetlen szabályos gazdagépi fájlban tárol, az epizódok életciklus-kezelése egyetlen fájlművelet lesz:

1. **100 milliszekundumos `env.reset()` a `cp --reflink=always` segítségével**:
   - Egyszer kell létrehozni egy `golden-docker.ext4` fájlt, amely előre letöltött alapimage-eket tartalmaz (`python:3.11`, `postgres:16`, `redis:7`, vagy feladatspecifikus `SWE-bench` alapimage-eket).
   - Minden RL-epizód elején a `cp --reflink=always golden-docker.ext4 ep-0042.ext4` parancs (XFS, Btrfs, ZFS vagy macOS APFS esetén) 100 milliszekundumon belül, a mögöttes lemezblokkok másolása nélkül hoz létre egy önálló másolás-íráskor klónt.
   - Csak az adott epizód során módosított 4 KiB-os blokkok foglalnak további lemezterületet.
2. **Nulla maradékot hagyó lebontás (`env.close()`)**:
   - A `rungv` folyamat leállítása (Go-ban `sb.Close()`) és az `ep-0042.ext4` fájl leválasztása (unlink) körülbelül 10 milliszekundum alatt felszabadítja az epizód összes folyamatát, hálózati socketjét, csatolását és tárhelyét. Semmi sem kerül a gazdagépi kernel csatolástáblázatába, és nem regisztrálódik gazdagépi cgroupokban.

---

## Lépésről lépésre munkafolyamat: Golden `.ext4` pillanatkép és gyors epizódvisszaállítás

A `rungv` eszközt bármely rollout-munkacsomóponton telepítheti: vagy a SLSA-attesztált, előre fordított binárist töltheti le a [GitHub Releases](https://github.com/gfire-sigs/gvx/releases) oldalról (`gh attestation verify rungv-v0.2.0-linux-amd64.tar.gz --repo gfire-sigs/gvx --signer-workflow gfire-sigs/gvx/.github/workflows/release.yml --deny-self-hosted-runners`), vagy a `CGO_ENABLED=0 go install z.gfire.dev/gvx/cmd/rungv@latest` parancs futtatásával.

### 1. lépés: A Golden `docker:dind` kötet egyszeri létrehozása

```sh
mkdir -p /srv/rl-snapshots /srv/rl-episodes

# 1. Seed docker:dind példány indítása a golden-docker.ext4 fájlra támaszkodva
rungv run \
  -p unix:/srv/rl-snapshots/seed.sock:2375 \
  --mount type=volume,src=/srv/rl-snapshots/golden-docker.ext4,dst=/var/lib/docker \
  -e DOCKER_TLS_CERTDIR= \
  docker:dind --tls=false &
SEED_PID=$!

# 2. Alapimage-ek és build-gyorsítótár előzetes feltöltése a golden-docker.ext4 fájlba
export DOCKER_HOST="unix:///srv/rl-snapshots/seed.sock"
until docker info >/dev/null 2>&1; do sleep 0.5; done

docker pull python:3.11-slim
docker pull redis:7-alpine
docker pull postgres:16-alpine

# 3. A seed példány szabályos leállítása, hogy az ext4lite kiírja és tömörítse az image-eket
kill -INT $SEED_PID
wait $SEED_PID
```

### 2. lépés: Párhuzamos RL-epizódok indítása 100 milliszekundum alatt

Minden párhuzamos rollout-munkafolyamat reflinken keresztül klónozza a `golden-docker.ext4` fájlt, majd elindít egy izolált `docker:dind` példányt, amelyben az összes image már jelen van a `/var/lib/docker` könyvtárban:

```sh
EPISODE_ID="ep-0042"
SOCK="/srv/rl-episodes/${EPISODE_ID}.sock"

# Azonnali másolás-íráskor (CoW) klón (~100 ms XFS/Btrfs/APFS esetén)
cp --reflink=always \
  /srv/rl-snapshots/golden-docker.ext4 \
  "/srv/rl-episodes/${EPISODE_ID}.ext4"

# Izolált, nem privilegizált epizód indítása 4 GiB RAM-mal és 2 CPU-val
rungv run \
  -m 4g --cpus 2 \
  -p "unix:${SOCK}:2375" \
  --mount "type=volume,src=/srv/rl-episodes/${EPISODE_ID}.ext4,dst=/var/lib/docker" \
  -e DOCKER_TLS_CERTDIR= \
  docker:dind --tls=false &
EP_PID=$!

export DOCKER_HOST="unix://${SOCK}"
until docker info >/dev/null 2>&1; do sleep 0.2; done

# A rollout-munkafolyamaton belül az image-ek azonnal elérhetők hálózati letöltés nélkül
docker images

# Epizód lebontása a jutalom kiszámítása után (~10 ms)
kill -KILL $EP_PID
rm -f "/srv/rl-episodes/${EPISODE_ID}.ext4" "${SOCK}"
```

---

## Programozott rollout-készlet a `z.gfire.dev/gvx/pkg/gvx` Go SDK használatával

Ha az RL-környezetkiszolgáló vagy az értékelő keretrendszer Go nyelven íródott (vagy gRPC-n keresztül egy Go rollout-démont hív), a párhuzamos konténerepizódokat közvetlenül a `z.gfire.dev/gvx/pkg/gvx` csomagon keresztül kezelheti:

```go
package main

import (
	"bytes"
	"context"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"time"

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

func runEpisode(ctx context.Context, goldenExt4, scratchDir string, epID int) error {
	epExt4 := filepath.Join(scratchDir, fmt.Sprintf("ep-%04d.ext4", epID))
	defer os.Remove(epExt4)

	// 1. A golden ext4lite kötet reflinkes klónozása
	cpCmd := exec.CommandContext(ctx, "cp", "--reflink=always", goldenExt4, epExt4)
	if err := cpCmd.Run(); err != nil {
		return fmt.Errorf("clone golden volume: %w", err)
	}

	// 2. Epizódonkénti falióra-időkorlát alkalmazása
	epCtx, cancel := context.WithTimeout(ctx, 2*time.Minute)
	defer cancel()

	var stdout, stderr bytes.Buffer
	sb, err := gvx.New(epCtx, gvx.Config{
		Platform:               gvx.PlatformAuto,
		NetworkMode:            gvx.NetModeNAT,
		NetRaw:                 true,
		AllowPacketSocketWrite: true,
		AllowSUID:              true,
		OCIImage:               "docker:dind",
		Entrypoint:             []string{"sh", "-c"},
		EntrypointSet:          true,
		Cmd: []string{
			"dockerd-entrypoint.sh --tls=false >/var/log/dockerd.log 2>&1 & " +
				"until docker info >/dev/null 2>&1; do sleep 0.2; done && " +
				"docker run --rm python:3.11-slim python -c 'print(6 * 7)'",
		},
		Envv: []string{"DOCKER_TLS_CERTDIR="},
		Mounts: []gvx.Mount{
			{
				Kind:      gvx.MountVolume,
				ImagePath: epExt4,
				GuestPath: "/var/lib/docker",
			},
		},
		Resources: gvx.Resources{
			MemoryBytes: 4 << 30, // 4 GiB korlát
			CPUMillis:   2000,    // 2,0 CPU
		},
		Stdout: &stdout,
		Stderr: &stderr,
	})
	if err != nil {
		return fmt.Errorf("init episode %d: %w", epID, err)
	}
	defer sb.Close()

	exitCode, err := sb.Run(epCtx)
	if err != nil {
		return fmt.Errorf("run episode %d: %w", epID, err)
	}

	log.Printf("episode %d finished: exit=%d stdout=%q", epID, exitCode, stdout.String())
	return nil
}

func main() {
	ctx := context.Background()
	if err := runEpisode(ctx, "/srv/rl-snapshots/golden-docker.ext4", "/srv/rl-episodes", 1); err != nil {
		log.Fatal(err)
	}
}
```

---

## Az Agent RL homokozó futtatókörnyezetek összehasonlítása

| Metrika / követelmény                                     | Megosztott gazdagépi `dockerd`    | Privilegizált `docker:dind` | Firecracker / KVM MicroVM          | Szabványos `gVisor` (`runsc`)      | `gvx` (`rungv` / `pkg/gvx`)                  |
| :-------------------------------------------------------- | :-------------------------------- | :-------------------------- | :--------------------------------- | :--------------------------------- | :------------------------------------------- |
| **Gazdagépi `root` vagy `--privileged` szükséges**        | Igen (`docker.sock` = root)       | Igen (`--privileged`)       | Szükséges `/dev/kvm` + `TAP` beállítás | Igen (vagy `userns` + `mount`) | **Nem (egyetlen nem privilegizált folyamat)** |
| **Működik nem privilegizált K8s podokban / meglévő `runsc`-ben** | Nem                        | Nem                         | Nem (nincs `/dev/kvm`)             | Sikertelen (`EBUSY` beágyazott seccomp esetén) | **Igen (automatikus futex loop tartalék)** |
| **Támogatja a belső `docker build` és `docker compose` műveleteket** | Megosztott gazdagépi daemont használ | Igen                | Igen                               | Sikertelen host DinD hangolás nélkül | **Igen (`overlayfs` `ext4lite`-on)**        |
| **Epizódonkénti hálózati izoláció**                       | Megosztott `docker0` / `xtables` zárolás | Külön névtér                | Külön VM NIC                       | Külön netns                        | **Izolált folyamaton belüli `netstack`**     |
| **Meleg epizódvisszaállítási késleltetés (`env.reset()`)** | 5 s és 30 s között (konténer/kötet törlés) | 10 s és 60 s között (hideg daemon) | ~150 ms (VM pillanatkép)     | 5 s és 20 s között                 | **~100 ms (`cp --reflink=always` `.ext4`)**  |
| **Többplatformos helyi fejlesztés (Windows / macOS / Linux)** | Linux VM szükséges             | Linux VM szükséges          | Csak Linux KVM                     | Csak Linux                         | **Natív Windows, macOS és Linux alatt**      |

---

## További olvasnivaló ebben a sorozatban

1. **[gvx: Linux-konténerek, Docker és Kubernetes futtatása egyetlen nem privilegizált folyamatban](/blog/posts/gvx-cross-platform-linux-containers-z48916d01)**: Teljes architekturális áttekintés a `gvx`-ről Windows (`whpx`, `systrap`), macOS (`hvf`) és Linux (`systrap`) rendszereken.
2. **[Docker, docker build és docker compose futtatása root nélkül vagy felhasználói névterek nélkül](/blog/posts/run-docker-without-root-or-userns-gvx-z48916d02)**: Gyors, 3 lépéses indítási és hibaelhárítási útmutató arra az esetre, ha a `sudo`, `unshare(CLONE_NEWUSER)`, `mount(2)` és `/dev/fuse` le van tiltva.
3. **[Docker-in-Docker futtatása gVisorban és beágyazott homokozókban a gvx segítségével](/blog/posts/docker-in-docker-inside-gvisor-with-gvx-z48916d03)**: Részletes elemzés arról, miért hibásodik meg a `docker.io` és a beágyazott `runsc` a `gVisor` (`runsc`) belsejében, és hogyan vált a `gvx` a `_RUN_SYSCALL_LOOP` futex loopra `EBUSY` hiba esetén.
4. **[Gyors, izolált Docker-környezetek AI-ágens RL-rolloutokhoz a gvx segítségével](/blog/posts/fast-docker-environments-for-agent-rl-rollouts-z48916d04)** (ez a bejegyzés)
