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 (TCP i UDP)
- Seccomp — filtrowanie syscalli z profili JSON
- Tryb rootless (user namespaces)
- Pods — grupy kontenerów ze wspólną siecią/PID/IPC
- REST API (axum) z opcjonalnym TLS (rustls) i Bearer token auth
- Eksport metryk w formacie Prometheus z realnym pomiarem CPU (delta)
- Structured logging (tracing) + OpenTelemetry OTLP exporter
- SQLite WAL jako backend stanu (zamiast JSON w /var/run)
- IPAM — pula IP z gwarancją braku kolizji
- Automatyczne restartowanie (
auto_restart) - PTY shell — wejście do działającego kontenera
- Systemd unit + socket activation
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.
Stan kontenerów i podów jest przechowywany w bazie SQLite w trybie WAL
(/var/lib/hackeros/state.db). Adresy IP są zarządzane przez
wbudowany moduł IPAM — każdy kontener dostaje unikalny sufiks z puli 2–254.
hco run
│
├─ ImageManager::resolve_image_layers() ← pobierz/cache OCI
├─ setup_overlayfs() ← zmontuj rootfs
├─ setup_bridge() / setup_cni() ← skonfiguruj sieć
├─ setup_cgroups() ← ogranicz zasoby
├─ db::ipam_allocate() ← przydziel unikalny IP
├─ clone(CLONE_NEWUTS|PID|NS|NET|IPC) ← nowe namespaces
│ └─ child_entrypoint()
│ ├─ setup_namespaces() ← user ns (rootless)
│ ├─ seccomp_setup() ← załaduj profil
│ ├─ sethostname()
│ ├─ bind mounts (walidowane)
│ ├─ pivot_root → /
│ └─ execve(cmd)
├─ create_veth_pair() ← sieć host↔kontener
├─ setup_port_forwarding() ← iptables DNAT (TCP+UDP)
├─ db::insert_container() ← zapisz stan + pełny HkConfig
└─ ContainerLogger::start_capture() ← capture stdout (100MB limit)
Moduły
lowerdir (read-only).
Zmiany trafiają do katalogu upper/ konkretnego kontenera.
Po zatrzymaniu kontenera katalog upper/ jest usuwany.
04 CLI — Komendy
-w dla live loophco run
hco run <name> -i <image> [opcje]
| Flaga | Opis | Przykład |
|---|---|---|
-i / --image | Obraz OCI do uruchomienia | alpine:latest |
-d / --detached | Uruchom w tle (daemon) | |
-p / --publish | Przekierowanie portu host:kontener[/proto] | 8080:80/tcp |
-v / --volume | Montowanie katalogu host:kontener | /data:/mnt/data |
-e / --env | Zmienna środowiskowa KEY=VALUE (powtarzalna) | -e FOO=bar |
--memory | Limit pamięci RAM | 512MB |
--cpu | Limit CPU w % (1–100) | 50 |
--auto-restart | Restart kontenera po zakończeniu | |
--rootless | Uruchom w trybie user namespaces |
# Uruchom nginx w tle z przekierowaniem portu
hco run my-nginx -i nginx:alpine -p 8080:80 -d
# Uruchom z limitem pamięci i CPU
hco run db -i postgres:15 -e POSTGRES_PASSWORD=secret \
--memory 512MB --cpu 50 -d
# Uruchom Alpine z wolumenem i auto-restartem
hco run dev-box -i alpine:latest -v /home/user/code:/app \
--auto-restart -d
# Uruchom w trybie interaktywnym (foreground)
hco run test -i alpine:latest
hco stop
hco stop <name_lub_id_prefix>
Wysyła SIGTERM, czeka 10 sekund (sprawdzając co 100 ms), następnie wysyła SIGKILL. Czyści iptables (DNAT + FORWARD), veth, OverlayFS, cgroups i wpis z bazy SQLite.
hco list / hco ps
hco list
hco ps
Wyświetla tabelę z kolumnami: ID (skrócony), NAME, IMAGE, STATUS, IP, POD. Dane pobierane z SQLite.
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> [-w]
Wyświetla statystyki pamięci i CPU z cgroups v2. Flaga -w / --watch włącza live refresh co 1 sekundę (bez czyszczenia całego ekranu — tylko kursor na górę).
hco image
# Usuń nieużywane warstwy obrazów (garbage collect)
hco image gc
# Importuj obraz z archiwum Docker save
hco image import my-image:local -f /tmp/myimage.tar
hco api
hco api [opcje]
| Flaga | Opis | Domyślnie |
|---|---|---|
--api-addr | Adres i port nasłuchu | 127.0.0.1:8080 |
--api-token | Bearer token dla autoryzacji | brak (dev mode) |
--tls-cert | Ścieżka do pliku PEM z certyfikatem | brak (HTTP) |
--tls-key | Ścieżka do pliku PEM z kluczem prywatnym | brak (HTTP) |
--json-logs | Logi w formacie JSON (structured) | wyłączone |
--otlp | Endpoint OTLP gRPC (OpenTelemetry) | brak |
--db | Ścieżka do pliku bazy SQLite | /var/lib/hackeros/state.db |
hco api \
--api-addr 0.0.0.0:8443 \
--api-token "$(cat /etc/hco/token)" \
--tls-cert /etc/hco/tls.crt \
--tls-key /etc/hco/tls.key \
--json-logs \
--otlp http://otel-collector:4317
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"
-> seccomp_profile = "/etc/hco/profiles/default.json"
[Network]
-> bridge_name = "hkbr0"
-> subnet = "10.10.0.0/24"
-> gateway = "10.10.0.1"
HkConfig) jest serializowana jako JSON i zapisywana
w kolumnie config_json w bazie SQLite. Dzięki temu restart_container()
może odtworzyć dokładnie te same parametry bez żadnych dodatkowych plików.
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 (1–100) | |
mounts | string | Montowania oddzielone przecinkami | |
port_mappings | string | Przekierowania portów host:kontenera[/proto] | |
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.
Każdy pod uruchamia proces pause (/usr/libexec/hco/pause),
który trzyma współdzielone przestrzenie nazw przez cały czas życia poda.
Jeśli binarium pause nie istnieje, używany jest fallback sleep infinity.
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
# Zrestartuj zatrzymane kontenery w podzie
hco pod start my-pod
# 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.
hco pod start <name> sprawdza każdy kontener w podzie przez SQLite.
Jeśli kontener nie działa, odczytuje jego config_json i restartuje
z dokładnie tymi samymi parametrami.
07 REST API
Po uruchomieniu hco api dostępny jest serwer HTTP/HTTPS (axum 0.7)
z endpointami do zarządzania kontenerami i podami. Serwer obsługuje paginację,
timeouty żądań (60 s), limit rozmiaru body (10 MB) oraz opcjonalną autoryzację
Bearer tokenem.
hco api --api-addr 0.0.0.0:8080
hco api \
--api-addr 0.0.0.0:8443 \
--api-token my-secret-token \
--tls-cert /etc/hco/tls.crt \
--tls-key /etc/hco/tls.key
Endpointy — Kontenery
| Metoda | Ścieżka | Opis |
|---|---|---|
| GET | /containers | Lista kontenerów (paginacja: ?page=1&per_page=50) |
| POST | /containers | Utwórz i uruchom nowy kontener (timeout 300 s) |
| DELETE | /containers/:id | Zatrzymaj i usuń kontener |
| POST | /containers/:id/start | Zrestartuj kontener (odczytuje config z SQLite) NOWE |
| POST | /containers/:id/stop | Zatrzymaj kontener |
| GET | /containers/:id/logs | Pobierz logi stdout kontenera |
Endpointy — Pods
| Metoda | Ścieżka | Opis |
|---|---|---|
| GET | /pods | Lista podów (paginacja: ?page=1&per_page=50) |
| POST | /pods | Utwórz i uruchom nowego poda (timeout 600 s) |
| DELETE | /pods/:name | Zatrzymaj i usuń poda |
| POST | /pods/:name/start | Zrestartuj zatrzymane kontenery w podzie NOWE |
| POST | /pods/:name/stop | Zatrzymaj poda |
Endpointy — System ZAKTUALIZOWANE
| Metoda | Ścieżka | Auth | Opis |
|---|---|---|---|
| GET | /health | publiczny | Health check — status, wersja, liczba działających kontenerów |
| GET | /metrics | publiczny | Metryki Prometheus text (Content-Type: text/plain; version=0.0.4) |
/health i /metrics nie wymagają tokenu auth —
są dostępne publicznie, co umożliwia scraping przez Prometheus i health check przez
load balancer bez przekazywania tokenu.
Paginacja
Listy kontenerów i podów obsługują paginację przez query string:
GET /containers?page=2&per_page=25
GET /pods?page=1&per_page=10
{
"containers": [...],
"total": 142,
"page": 2,
"per_page": 25
}
Przykład — tworzenie kontenera (curl)
curl -X POST https://localhost:8443/containers \
-H "Content-Type: application/json" \
-H "Authorization: Bearer my-secret-token" \
-d '{
"name": "my-nginx",
"image": "nginx:alpine",
"ports": ["8080:80/tcp"],
"env": ["NGINX_ENTRYPOINT_QUIET_LOGS=1"],
"memory_limit": "128MB",
"cpu_percent": 25,
"auto_restart": true
}'
{ "id": "a3f7c2d1-8b4e-4f2a-b1c3-d5e6f7a8b9c0" }
Health check
curl https://localhost:8443/health
{
"status": "ok",
"version": "0.3.0",
"containers_running": 5
}
Schemat błędów
| HTTP | Kiedy |
|---|---|
400 Bad Request | Nieprawidłowy input — błąd walidacji nazwy, obrazu, portu, montowania, timeout startu |
401 Unauthorized | Brakujący lub nieprawidłowy Bearer token |
404 Not Found | Kontener lub pod nie istnieje |
500 Internal Server Error | Błąd runtime — szczegóły w polu error |
{ "error": "Invalid port mapping '99999:80': port numbers must be > 0" }
08 Autoryzacja API NOWE
API obsługuje opcjonalną autoryzację przez Bearer token.
Gdy --api-token jest podany, wszystkie chronione endpointy
wymagają nagłówka Authorization: Bearer <token>.
Brak tokenu lub nieprawidłowy token zwraca 401 Unauthorized.
--api-token nie jest podany, API działa bez autoryzacji.
W środowisku produkcyjnym zawsze ustaw token i włącz TLS.
# Ustaw token przy starcie
hco api --api-token "$(openssl rand -hex 32)"
# Użyj tokenu w żądaniach
curl -H "Authorization: Bearer <token>" \
https://localhost:8443/containers
Endpointy GET /health i GET /metrics są publiczne
— nie wymagają tokenu, co umożliwia zewnętrzny scraping metryk i health check
przez load balancer.
09 TLS / HTTPS NOWE
Serwer API obsługuje TLS przez bibliotekę rustls (bez OpenSSL). Certyfikat i klucz prywatny podajesz w formacie PEM. Obsługiwane formaty klucza: PKCS8 i RSA PKCS1.
Generowanie self-signed certyfikatu (dev)
mkdir -p /etc/hco
openssl req -x509 -newkey rsa:4096 -keyout /etc/hco/tls.key \
-out /etc/hco/tls.crt -days 365 -nodes \
-subj "/CN=hco-api/O=HackerOS"
Uruchomienie z TLS
hco api \
--api-addr 0.0.0.0:8443 \
--tls-cert /etc/hco/tls.crt \
--tls-key /etc/hco/tls.key \
--api-token my-secret
--tls-cert lub --tls-key są podane, ale pliki
nie istnieją, serwer automatycznie wraca do trybu plain HTTP z ostrzeżeniem w logach.
Implementacja
TLS loop w src/api.rs akceptuje połączenia przez tokio::net::TcpListener,
opakowuje je w tokio_rustls::TlsAcceptor i podaje do hyper 1.x
przez adapter TowerToHyperService (bridge między tower::Service
a hyper::service::Service).
10 Metryki Prometheus ZAKTUALIZOWANE
Serwer API eksportuje metryki pod GET /metrics w formacie
Prometheus text. Metryki CPU są teraz realne — background task
(spawn_metrics_collector) co 1 sekundę czyta cpu.stat
z cgroup v2, oblicza deltę usage_usec i przelicza na procenty
z uwzględnieniem liczby rdzeni CPU.
| Metryka | Typ | Opis |
|---|---|---|
hco_containers_total | Gauge | Łączna liczba kiedykolwiek stworzonych kontenerów |
hco_containers_running | Gauge | Aktualnie działające kontenery |
hco_container_memory_bytes | GaugeVec | Użycie pamięci z memory.current (labels: id, name) |
hco_container_cpu_usage_percent | GaugeVec | Rzeczywiste użycie CPU % w oknie 1 s (labels: id, name) |
hco_container_start_total | Counter | Łączna liczba startów kontenerów |
usage_usec z cgroup v2, oblicza:
cpu% = (Δusage_usec / Δwall_usec) * 100 / num_cpus.
# HELP hco_containers_running Number of currently running containers
# TYPE hco_containers_running gauge
hco_containers_running 3
# HELP hco_container_memory_bytes Memory usage in bytes
# TYPE hco_container_memory_bytes gauge
hco_container_memory_bytes{id="a3f7...",name="my-nginx"} 1.24e+07
# HELP hco_container_cpu_usage_percent CPU usage percent (1-second window)
# TYPE hco_container_cpu_usage_percent gauge
hco_container_cpu_usage_percent{id="a3f7...",name="my-nginx"} 2.3
Konfiguracja Prometheus scrape
scrape_configs:
- job_name: 'hco'
static_configs:
- targets: ['localhost:8080']
metrics_path: /metrics
scrape_interval: 5s
11 Observability / OpenTelemetry NOWE
hco używa biblioteki tracing do structured logging.
Wspiera eksport tracingów przez protokół OTLP gRPC do OpenTelemetry Collector,
Jaeger, Tempo lub innego backendu.
Structured logging
Domyślnie logi są wypisywane w formacie tekstowym. Flaga --json-logs włącza format JSON:
hco api --json-logs 2>&1 | jq .
{
"timestamp": "2025-05-18T12:34:56.789Z",
"level": "INFO",
"target": "hco::container",
"fields": {
"id": "a3f7c2d1",
"name": "my-nginx",
"pid": 12345,
"ip": "10.10.0.5",
"message": "Container started"
}
}
OpenTelemetry OTLP
Flaga --otlp włącza eksport tracingów do OTLP endpoint (gRPC):
hco api --otlp http://localhost:4317 --json-logs
JsonFields dla trait bound OpenTelemetryLayer).
Poziom logowania
Steruj poziomem przez zmienną środowiskową:
# Pokaż tylko błędy i ostrzeżenia
RUST_LOG=warn hco api
# Debug dla modułu hco::container
RUST_LOG=warn,hco::container=debug hco api
12 Seccomp / Bezpieczeństwo
hco obsługuje filtrowanie syscalli przez seccomp przy użyciu
biblioteki libseccomp. Profile są plikami JSON kompatybilnymi
ze schematem Docker/Podman.
Walidacja inputów
Moduł src/validation.rs waliduje wszystkie dane wejściowe CLI i API:
- Nazwy — tylko
[a-zA-Z0-9_-], max 128 znaków - Obrazy — blokuje metaznaki shell (
$ ; & | ` \ { }) - Montowania — blokuje path traversal (
../), wymaga ścieżek absolutnych, blokuje wrażliwe ścieżki (/proc,/sys,/etc/shadowitd.) - Porty — format
host:container[/tcp|udp], zakres 1–65535 - Env — klucz musi pasować do
[A-Za-z_][A-Za-z0-9_]* - Memory limit — format
\d+(B|KB|MB|GB) - CPU percent — zakres 1–100
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ść) |
13 Stan — SQLite NOWE
Stan kontenerów, podów i alokacji IP jest przechowywany w bazie danych SQLite
w trybie WAL (Write-Ahead Logging). Zastępuje poprzednie podejście z plikami JSON
w /var/run/hackeros/, eliminując race conditions przy równoległych operacjach.
Lokalizacja bazy
/var/lib/hackeros/state.db
Można zmienić przez flagę --db <path> przy starcie hco api.
Schemat bazy
| Tabela | Zawartość |
|---|---|
containers | Stan kontenera + pełny HkConfig jako JSON w kolumnie config_json. Umożliwia restart po zatrzymaniu. |
pods | Stan poda + spec YAML jako JSON. Lista ID kontenerów w container_ids_json. |
ipam | Pula adresów IP — sufiks (2–254), container_id, subnet_prefix, flaga released. |
schema_version | Wersja schematu (migracje automatyczne). |
sqlite3 /var/lib/hackeros/state.db \
"SELECT id, name, image, status, ip_address FROM containers;"
# Sprawdź alokacje IP
sqlite3 /var/lib/hackeros/state.db \
"SELECT container_id, suffix, released FROM ipam;"
db::ipam_allocate(). Po zatrzymaniu kontenera sufiks jest
oznaczany jako released=1 i może być ponownie użyty.
Eliminuje kolizje IP przy dużej liczbie kontenerów.
14 Systemd / Socket Activation NOWE
hco dostarcza plik unit systemd (hco-api.service)
oraz opcjonalny plik socket (hco-api.socket) dla socket activation.
Instalacja
sudo cp hco-api.service /etc/systemd/system/
sudo cp hco-api.socket /etc/systemd/system/ # opcjonalnie
sudo systemctl daemon-reload
sudo systemctl enable --now hco-api.service
Konfiguracja przez EnvironmentFile
Utwórz plik /etc/hco/hco.env z nadpisaniami:
HCO_API_ADDR=0.0.0.0:8443
HCO_API_TOKEN=my-production-secret
HCO_TLS_CERT=/etc/hco/tls.crt
HCO_TLS_KEY=/etc/hco/tls.key
HCO_OTLP=http://otel-collector:4317
RUST_LOG=hco=info
Zarządzanie serwisem
# Status serwisu
systemctl status hco-api
# Logi (journald)
journalctl -u hco-api -f
# Restart
systemctl restart hco-api
Socket Activation
Plik hco-api.socket umożliwia uruchomienie serwisu dopiero
przy pierwszym połączeniu na port 8080. Oszczędza zasoby przy starcie systemu.
sudo systemctl enable --now hco-api.socket
# hco-api.service uruchomi się automatycznie przy pierwszym połączeniu
CapabilityBoundingSet ogranicza do niezbędnego minimum:
CAP_SYS_ADMIN, CAP_NET_ADMIN, CAP_MKNOD,
CAP_SETUID, CAP_SETGID, CAP_CHOWN,
CAP_DAC_OVERRIDE, CAP_SYS_CHROOT.
15 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. Adres IP jest przydzielany
przez IPAM z gwarancją unikalności.
Tryby sieci
| Tryb | Opis |
|---|---|
bridge | Domyślny. Most hkbr0, veth, iptables NAT/DNAT (TCP i UDP) |
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 (zarządzane przez IPAM)
NAT: iptables MASQUERADE na ruch wychodzący
FORWARD: reguły ACCEPT dla każdego przekierowanego portu
Przekierowanie portów
Reguły iptables DNAT są dodawane dla każdego mapowania portów.
Obsługiwane protokoły: tcp i udp.
Nieużywany interfejs veth host-side jest usuwany przez ip link del
po zatrzymaniu kontenera (nazwa zapisana w SQLite jako veth_host).
hco run dns -i coredns:latest -p 5353:53/udp -d
db::ipam_allocate().
Po zatrzymaniu kontenera adres jest zwalniany (released=1) i może być
ponownie użyty. Eliminuje kolizje przy dużej liczbie kontenerów.
16 Obrazy OCI
hco pobiera obrazy bezpośrednio z rejestrów OCI (Docker Hub, prywatne)
bez potrzeby instalowania Dockera. Warstwy są buforowane lokalnie.
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 warstw i timeouty
Warstwy obrazów są zapisywane w /var/lib/hackeros/layers/.
Przy ponownym użyciu tej samej warstwy (identyczny digest SHA256) pobieranie
jest pomijane. Każda pobrana warstwa jest weryfikowana przez SHA256.
| Operacja | Timeout |
|---|---|
| Pobieranie manifestu / auth token | 30 s |
| Pobieranie warstwy | 300 s |
| Start kontenera (API) | 300 s |
| Start poda (API) | 600 s |
Garbage collect
# Usuń warstwy nieużywane przez żaden obraz
hco image gc
Import z archiwum tar
hco image import my-image:local -f /tmp/myimage.tar
17 Błędy i diagnostyka
hco używa biblioteki miette do czytelnych komunikatów błędów
z kontekstem i wskazówkami. Logowanie odbywa się przez tracing
z filtrem kontrolowanym przez RUST_LOG.
Logi kontenerów
Stdout kontenera jest przechwytywany do pliku z limitem 100 MB i rotacją
3 plików (np. .log.1, .log.2, .log.3):
/var/log/hackeros/<container-id>.log
tail -f /var/log/hackeros/a3f7c2d1-8b4e-4f2a-b1c3-d5e6f7a8b9c0.log
# Lub przez API:
curl -H "Authorization: Bearer <token>" \
https://localhost:8443/containers/a3f7c/logs | jq .logs
Rollback przy błędzie startu
Jeśli start kontenera nie powiedzie się na dowolnym etapie (np. błąd sieci
po zamontowaniu OverlayFS), struktura StartResources automatycznie
cofa wszystkie operacje: odmontowuje overlayfs, usuwa veth, czyści reguły iptables,
usuwa wpis z SQLite i zwalnia IP z IPAM.
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 |
Cannot bind 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 SQLite | Sprawdź hco list |
IPAM pool exhausted | Brak wolnych adresów IP (wszystkie 253 zajęte) | Zatrzymaj nieużywane kontenery |
Invalid mount spec | Ścieżka relatywna, traversal lub wrażliwa ścieżka | Użyj bezwzględnej ścieżki poza /proc, /sys |
Cannot open TLS cert/key | Plik nie istnieje lub brak uprawnień odczytu | Sprawdź ścieżki i chmod 600 /etc/hco/tls.key |
Failed to create seccomp filter | Kernel nie obsługuje seccomp lub brak libseccomp | Sprawdź CONFIG_SECCOMP i zainstaluj libseccomp-dev |
Unauthorized | Brakujący lub nieprawidłowy Bearer token | Dodaj nagłówek Authorization: Bearer <token> |
18 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.