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
hco wymaga uprawnień root lub odpowiednio skonfigurowanych
user namespaces. Większość funkcji sieciowych wymaga roota.
02 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.
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
lowerdir (read-only).
Zmiany trafiają do katalogu upper/ konkretnego kontenera.
Po zatrzymaniu kontenera katalog upper/ jest usuwany.
04 CLI — Komendy
hco run
hco run <name> -i <image> [opcje]
| Flaga | Opis | Przykład |
|---|---|---|
-i / --image | Obraz 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 |
# 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
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
hco enter <name_lub_id>
Otwiera interaktywną sesję PTY w przestrzeniach nazw działającego kontenera. Wymaga roota.
hco stats
hco stats <name_lub_id>
Wyświetla live statystyki pamięci i CPU z cgroups v2 (odświeżanie co 1s).
hco api
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().
[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
| Sekcja | Pole | Typ | Opis |
|---|---|---|---|
[Metadata] | name | string | 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)
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
# 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: 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.
hco api --api-addr 0.0.0.0:8080
Endpointy — Kontenery
| Metoda | Ścieżka | Opis |
|---|---|---|
| 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żka | Opis |
|---|---|---|
| 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żka | Opis |
|---|---|---|
| GET | /metrics | Metryki w formacie Prometheus text |
Przykład — tworzenie kontenera (curl)
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
}'
{ "id": "a3f7c2d1-8b4e-..." }
Schemat błędu
{ "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.
| Metryka | Typ | Opis |
|---|---|---|
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 |
# 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_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
| Akcja | Efekt |
|---|---|
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
[Security]
-> seccomp_profile = "/etc/hco/profiles/default.json"
-> rootless = false
-> readonly_root = false
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
| Tryb | Opis |
|---|---|
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
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
| Format | Przykład | Rozwinię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
// 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
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łąd | Przyczyna | Rozwią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.