BACK
// HackerOS Project — Container Runtime

HackerOS Containers

Zaawansowane środowisko uruchomieniowe dla kontenerów napisane w języku Rust. Obsługuje przestrzenie nazw Linux, OverlayFS, cgroups v2, seccomp, CNI, REST API oraz automatyczne restartowanie procesów.

Rust 2021 Linux Namespaces OverlayFS cgroups v2 Seccomp REST API CNI Prometheus

01 Przegląd

hco (HackerOS Containers) to lekki, niskopoziomowy runtime kontenerów napisany w Rust. Nie zależy od Dockera ani containerd — zarządza cyklem życia kontenerów bezpośrednio przez syscalle Linuksa.

Główne możliwości:

  • Izolacja przez przestrzenie nazw (UTS, PID, MNT, NET, IPC, USER)
  • OverlayFS — wielowarstwowy system plików jak w Dockerze
  • Ograniczenia zasobów przez cgroups v2 (pamięć, CPU)
  • Pobieranie obrazów OCI z rejestrów (Docker Hub, własne)
  • Przekierowanie portów przez iptables/DNAT
  • Seccomp — filtrowanie syscalli z profili JSON
  • Tryb rootless (user namespaces)
  • Pods — grupy kontenerów ze wspólną siecią/PID/IPC
  • REST API (axum) do zarządzania przez HTTP
  • Eksport metryk w formacie Prometheus
  • Automatyczne restartowanie (auto_restart)
  • PTY shell — wejście do działającego kontenera
⚠ WYMAGANIA Uruchomienie hco wymaga uprawnień root lub odpowiednio skonfigurowanych user namespaces. Większość funkcji sieciowych wymaga roota.

02 Instalacja

HackerOS Linux — instalacja
hacker unpack hackeros-containers

Powyższa komenda pobierze i zainstaluje najnowszą wersję hco wraz ze wszystkimi zależnościami. Po zakończeniu procesu hco będzie dostępne w systemie.

ℹ Uwaga Jeśli używasz innej dystrybucji, skompiluj ze źródeł lub pobierz binaria z repozytorium GitHub.

03 Architektura

Kontener jest tworzony przez wywołanie nix::sched::clone() z odpowiednimi flagami przestrzeni nazw. Proces potomny wywołuje child_entrypoint(), który konfiguruje sieć, montuje OverlayFS, wykonuje pivot_root i uruchamia docelowy program przez execve.

hco run
  │
  ├─ ImageManager::resolve_image_layers()   ← pobierz/cache OCI
  ├─ setup_overlayfs()                      ← zmontuj rootfs
  ├─ setup_bridge() / setup_cni()           ← skonfiguruj sieć
  ├─ setup_cgroups()                        ← ogranicz zasoby
  ├─ clone(CLONE_NEWUTS|PID|NS|NET|IPC)     ← nowe namespaces
  │     └─ child_entrypoint()
  │           ├─ setup_namespaces()         ← user ns (rootless)
  │           ├─ seccomp_setup()            ← załaduj profil
  │           ├─ sethostname()
  │           ├─ bind mounts
  │           ├─ pivot_root → /
  │           └─ execve(cmd)
  ├─ create_veth_pair()                     ← sieć host↔kontener
  ├─ setup_port_forwarding()                ← iptables DNAT
  └─ ContainerLogger::start_capture()      ← capture stdout
ℹ OVERLAYFS Warstwy obrazu są montowane jako lowerdir (read-only). Zmiany trafiają do katalogu upper/ konkretnego kontenera. Po zatrzymaniu kontenera katalog upper/ jest usuwany.

04 CLI — Komendy

run
Uruchom nowy kontener z obrazu OCI
stop
Zatrzymaj działający kontener
list
Wyświetl wszystkie kontenery
enter
Wejdź do kontenera przez PTY shell
stats
Monitoruj zasoby kontenera (live)
pod
Zarządzaj grupami kontenerów (pods)
api
Uruchom serwer REST API

hco run

składnia
hco run <name> -i <image> [opcje]
alpine:latest
FlagaOpisPrzykład
-i / --imageObraz OCI do uruchomienia
-d / --detached
Uruchom w tle (daemon)

-p / --publish
Przekierowanie portu host:kontener
8080:80
-v / --volume
Montowanie katalogu host:kontener
/data:/mnt/data
przykłady
# Uruchom nginx w tle z przekierowaniem portu
hco run my-nginx -i nginx:alpine -p 8080:80 -d

# Uruchom Alpine z wolumenem
hco run dev-box -i alpine:latest -v /home/user/code:/app -d

# Uruchom w trybie interaktywnym (foreground)
hco run test -i alpine:latest

hco stop

składnia
hco stop <name_lub_id_prefix>

Wysyła SIGTERM, czeka 5 sekund, następnie wysyła SIGKILL. Czyści iptables, OverlayFS i cgroups.

hco enter

składnia
hco enter <name_lub_id>

Otwiera interaktywną sesję PTY w przestrzeniach nazw działającego kontenera. Wymaga roota.

hco stats

składnia
hco stats <name_lub_id>

Wyświetla live statystyki pamięci i CPU z cgroups v2 (odświeżanie co 1s).

hco api

składnia
hco api [--api-addr 0.0.0.0:8080]

Uruchamia serwer HTTP REST API. Domyślny adres: 127.0.0.1:8080.

05 Pliki konfiguracyjne (.hk)

Kontenery można opisywać plikami .hk — własnym formatem konfiguracyjnym HackerOS. Pliki te są ładowane przez HkConfig::from_file().

przykład — myapp.hk
[Metadata]
-> name = "my-app"
-> version = "1.0"
-> authors = "devops@example.com"
-> license = "MIT"

[Specs]
-> base_image = "alpine:latest"
-> memory_limit = "256MB"
-> cpu_percent = 50
-> mounts = "/data:/mnt/data"
-> port_mappings = "8080:80"
-> env = "APP_ENV=production,LOG_LEVEL=info"
-> cmd = "/usr/bin/myapp,--config,/etc/app.conf"

[Runtime]
-> auto_restart = true
-> network_mode = "bridge"

[Security]
-> rootless = false
-> readonly_root = false
-> drop_caps = "CAP_SYS_ADMIN"

[Network]
-> bridge_name = "hkbr0"
-> subnet = "10.10.0.0/24"
-> gateway = "10.10.0.1"

Sekcje konfiguracji

SekcjaPoleTypOpis
[Metadata]namestring
Nazwa kontenera
version
string
Wersja obrazu/konfiguracji
authors
string
Autorzy
license
string
Licencja
[Specs]base_image
string
Obraz OCI (np. alpine:latest)
memory_limit
string
Limit pamięci: 256MB, 1GB
cpu_percent
number
Limit CPU w procentach (0–100)
mounts
string
Montowania oddzielone przecinkami
port_mappings
string
Przekierowania portów host:kontenera
env
string
Zmienne środowiskowe KEY=val
cmd
string
Komenda do uruchomienia
[Runtime]
auto_restart
bool
Automatyczny restart po zakończeniu
network_mode
string
bridge | cni | none
cni_network
string
Nazwa sieci CNI (opcjonalne)
[Security]
rootless
bool
Tryb bez roota (user namespaces)
readonly_root
bool
Read-only rootfs
drop_caps
string
Capabilities do usunięcia
allow_raw_sockets
bool
Zezwól na gniazda raw
seccomp_profile
string
Ścieżka do profilu JSON seccomp

06 Pods

Pod to grupa kontenerów współdzielących przestrzenie nazw sieci, PID i/lub IPC. Wzorowane na Kubernetes Pods — kontenery w jednym podzie widzą się nawzajem przez localhost.

Plik specyfikacji poda (YAML)

my-pod.yaml
name: web-pod
shared_network: true
shared_pid: false
shared_ipc: true
containers:
  - metadata:
      name: web
      version: "1.0"
      authors: ""
      license: ""
    specs:
      base_image: nginx:alpine
      port_mappings: ["80:80"]
      mounts: []
      env: []
      cmd: []
    runtime:
      auto_restart: false
      network_mode: none
    security:
      rootless: false
      readonly_root: false
      allow_raw_sockets: true
      drop_caps: []
  - metadata:
      name: sidecar
    specs:
      base_image: alpine:latest
      cmd: ["/bin/sh", "-c", "while true; do sleep 5; done"]

Komendy pod

bash
# Utwórz i uruchom poda ze specyfikacji YAML
hco pod create my-pod -f my-pod.yaml

# Wyświetl działające pods
hco pod list

# Zatrzymaj poda (i wszystkie jego kontenery)
hco pod stop my-pod
ℹ SHARED NETWORK Gdy shared_network: true, tworzony jest dedykowany network namespace dla całego poda przez ip netns add pod-<name>. Wszystkie kontenery w podzie używają network_mode: none i wchodzą do wspólnego netns.

07 REST API

Po uruchomieniu hco api dostępny jest serwer HTTP (axum) z endpointami do zarządzania kontenerami i podami.

uruchomienie
hco api --api-addr 0.0.0.0:8080

Endpointy — Kontenery

MetodaŚcieżkaOpis
GET
/containers
Lista wszystkich kontenerów
POST
/containers
Utwórz i uruchom nowy kontener
DELETE
/containers/:id
Zatrzymaj i usuń kontener
POST
/containers/:id/start
Uruchom zatrzymany kontener (TODO)
POST
/containers/:id/stop
Zatrzymaj kontener
GET
/containers/:id/logs
Pobierz logi stdout kontenera

Endpointy — Pods

MetodaŚcieżkaOpis
GET
/pods
Lista wszystkich podów
POST
/pods
Utwórz i uruchom nowego poda
DELETE
/pods/:name
Zatrzymaj i usuń poda
POST
/pods/:name/stop
Zatrzymaj poda

Endpointy — System

MetodaŚcieżkaOpis
GET
/metrics
Metryki w formacie Prometheus text

Przykład — tworzenie kontenera (curl)

bash
curl -X POST http://localhost:8080/containers \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-nginx",
    "image": "nginx:alpine",
    "ports": ["8080:80"],
    "memory_limit": "128MB",
    "cpu_percent": 25,
    "auto_restart": true,
    "detached": true
  }'
odpowiedź — 201 Created
{ "id": "a3f7c2d1-8b4e-..." }

Schemat błędu

JSON — 500 Internal Server Error
{ "error": "Container not found: my-nginx" }

08 Metryki Prometheus

Serwer API eksportuje metryki pod GET /metrics w formacie Prometheus text. Można je zbierać standardowym scrapingiem.

MetrykaTypOpis
containers_total
Gauge
Łączna liczba kiedykolwiek stworzonych kontenerów
containers_running
Gauge
Aktualnie działające kontenery
container_memory_bytes
GaugeVec
Użycie pamięci (labels: id, name)
container_cpu_usage_percent
GaugeVec
Użycie CPU w % (labels: id, name)
container_start_total
Counter
Łączna liczba startów kontenerów
przykładowe dane
# HELP containers_running Number of currently running containers
# TYPE containers_running gauge
containers_running 3

# HELP container_memory_bytes Memory usage in bytes
# TYPE container_memory_bytes gauge
container_memory_bytes{id="a3f7...",name="my-nginx"} 1.24e+07

09 Seccomp / Bezpieczeństwo

hco obsługuje filtrowanie syscalli przez seccomp przy użyciu biblioteki libseccomp. Profile są plikami JSON kompatybilnymi ze schematem Docker/Podman.

Format profilu seccomp (JSON)

default-profile.json
{
  "default_action": "SCMP_ACT_ERRNO",
  "architectures": ["x86_64", "aarch64"],
  "syscalls": [
    {
      "names": ["read", "write", "open", "close", "stat",
                "fstat", "lstat", "poll", "lseek", "mmap",
                "mprotect", "munmap", "brk", "rt_sigaction",
                "rt_sigprocmask", "ioctl", "access", "pipe",
                "select", "nanosleep", "getpid", "fork",
                "execve", "exit", "exit_group", "getdents64"],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

Dostępne akcje

AkcjaEfekt
SCMP_ACT_ALLOW
Przepuść syscall
SCMP_ACT_ERRNO
Zwróć EPERM (domyślny błąd)
SCMP_ACT_ERRNO(N)
Zwróć errno o numerze N
SCMP_ACT_KILL
Zabij wątek
SCMP_ACT_KILL_PROCESS
Zabij cały proces
SCMP_ACT_TRAP
Wyślij SIGSYS
SCMP_ACT_LOG
Loguj (przepuść)

Użycie profilu w konfiguracji

myapp.hk — sekcja [Security]
[Security]
-> seccomp_profile = "/etc/hco/profiles/default.json"
-> rootless = false
-> readonly_root = false
🔒 BEZPIECZEŃSTWO Domyślnie, jeśli nie podano profilu seccomp, kontener nie ma żadnych ograniczeń na poziomie syscalli. Zawsze stosuj profil seccomp w środowiskach produkcyjnych.

10 Sieć / CNI

Domyślny tryb sieciowy to bridge. Każdy kontener dostaje parę interfejsów veth: jeden po stronie hosta (podłączony do mostu hkbr0), drugi wewnątrz kontenera jako eth0.

Tryby sieci

TrybOpis
bridge
Domyślny. Most hkbr0, veth, iptables NAT/DNAT
cni
Zewnętrzne wtyczki CNI przez cnitool
none
Brak sieci (używane przez kontenery w podach ze shared_network)

Konfiguracja mostu

Most jest tworzony automatycznie przy pierwszym uruchomieniu:

Domyślna podsieć: 10.10.0.0/24
Gateway:         10.10.0.1  (przypisany do hkbr0)
IP kontenerów:   10.10.0.2 — 10.10.0.254
NAT:             iptables MASQUERADE na ruch wychodzący
ℹ IP DETERMINIZM Adres IP kontenera jest wyznaczany jako 10.10.0.(container_id[0] % 250 + 2). Nie jest to deterministyczne między restartami — używaj DNS lub serwis discovery dla stabilnych adresów.

11 Obrazy OCI

hco pobiera obrazy bezpośrednio z rejestrów OCI (Docker Hub, prywatne) bez potrzeby instalowania Dockera.

Format referencji obrazu

FormatPrzykładRozwinięcie
name
alpine
registry-1.docker.io/library/alpine:latest
name:tag
nginx:alpine
registry-1.docker.io/library/nginx:alpine
user/repo:tag
myuser/myapp:v1
registry-1.docker.io/myuser/myapp:v1
registry/repo:tag
ghcr.io/org/app:latest
Bezpośrednie użycie rejestru

Cache obrazów

Warstwy obrazów są zapisywane w /var/lib/hackeros/images/ i /var/lib/hackeros/layers/. Przy ponownym uruchomieniu tego samego obrazu pobieranie jest pomijane.

Import z archiwum tar

API
// Programatycznie (Rust)
ImageManager::import_tar(Path::new("/tmp/myimage.tar"), "myimage:local")?;

12 Błędy i diagnostyka

hco używa biblioteki miette do czytelnych komunikatów błędów z kontekstem i wskazówkami.

Logi kontenerów

Stdout kontenera jest przechwytywany do pliku:

/var/log/hackeros/<container-id>.log
bash — podgląd logów
tail -f /var/log/hackeros/a3f7c2d1-8b4e-4f2a-b1c3-d5e6f7a8b9c0.log

# Lub przez API:
curl http://localhost:8080/containers/a3f7c/logs | jq .logs

Typowe błędy

BłądPrzyczynaRozwiązanie
Failed to clone container process
Brak uprawnień root lub brak obsługi namespace
Uruchom jako root lub włącz user namespaces w kernelu
Failed to bind to addr
Port zajęty lub brak uprawnień
Sprawdź ss -tlnp, zmień port API
Failed to get manifest
Brak dostępu do rejestru lub zły tag obrazu
Sprawdź połączenie i nazwę obrazu
Digest mismatch
Uszkodzona warstwa podczas pobierania
Usuń cache: rm -rf /var/lib/hackeros/images/<img>
Container not found
Podany ID/nazwa nie istnieje w /var/run/hackeros/
Sprawdź hco list
Failed to create seccomp filter
Kernel nie obsługuje seccomp lub brak libseccomp
Sprawdź CONFIG_SECCOMP i zainstaluj libseccomp-dev

13 Licencja

HackerOS Containers jest udostępniany na licencji MIT.

Copyright (c) HackerOS Team <hackeros068@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.