Skip to content

czhao-dev/container-runtime

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mini-run

A minimal container runtime CLI in Go — the core primitives real runtimes (runc) use, without image management, overlayfs, a daemon, or networking:

  • Namespace isolationCLONE_NEWPID (container sees itself as PID 1), CLONE_NEWNS (isolated mount table), CLONE_NEWUTS (custom hostname), CLONE_NEWIPC (isolated IPC), via syscall.SysProcAttr.Cloneflags.
  • Filesystem jailing via pivot_root — not chroot: the old root is fully unmounted and detached, preventing container breakout.
  • cgroups v2 resource limits — per-container memory ceiling and CPU quota under /sys/fs/cgroup/mini-run/<id>/.
  • Interactive PTY passthrough — stdio is wired straight through so /bin/sh, top, etc. work interactively.

It is a stateless CLI, not a daemon: sudo mini-run run <rootfs> <cmd> [args...] against a rootfs directory you've already unpacked yourself (e.g. Alpine's minirootfs tarball, extracted).

Requirements

Namespaces, pivot_root, and cgroups v2 are Linux kernel features and do not exist on macOS/Windows. Building the CLI works anywhere (Go's build tags isolate the Linux-only code), but actually running a container requires Linux, root, and a cgroups v2 unified hierarchy mounted at /sys/fs/cgroup.

Dev/test environment (macOS)

A Lima config is included for a disposable Ubuntu VM:

brew install lima
limactl start --name mini-run ./lima.yaml
limactl shell mini-run
cd container-runtime
go build -o mini-run ./cmd/mini-run
./scripts/fetch-rootfs.sh
sudo ./mini-run run --memory 128m --cpus 0.5 ./rootfs /bin/sh

(Ubuntu/systemd is used rather than Alpine/OpenRC because systemd keeps the root cgroup free of directly-attached processes — otherwise enabling the cpu/memory controllers on /sys/fs/cgroup fails with EBUSY.)

If you already have a Linux box, skip Lima and just go build + sudo ./mini-run run ... there directly.

Usage

sudo mini-run run [--memory 512m] [--cpus 0.5] <rootfs-path> <cmd> [args...]
  • --memory — e.g. 512m, 1.5g (default: unlimited)
  • --cpus — fraction of one core, e.g. 0.5, 2 (default: unlimited)

Flags must precede <rootfs-path>; everything after the command is passed through untouched (so sudo mini-run run ./rootfs /bin/sh -c "ls -la" works as expected).

Verification

Run inside the Lima VM (or any Linux box):

  1. PID namespace: echo $$ inside the container prints 1.
  2. UTS namespace: hostname prints a generated mini-run-xxxxxxxx name, distinct from the host's.
  3. Mount namespace: mount inside the container shows only /, /proc, and the synthetic /dev tmpfs — compare against a second limactl shell mini-run window on the host.
  4. Process visibility: ps aux inside the container shows only the container's own processes, not the host's (/proc reflects the new PID namespace).
  5. Breakout prevention: ls /.old_root inside the container fails with "No such file or directory"; ls / shows only the rootfs's own directories, never host paths like /home or the project directory.
  6. cgroup limits applied: from the host, cat /sys/fs/cgroup/mini-run/<id>/memory.max and .../cpu.max match what was requested; cgroup.procs shows the real host-namespace PID (vs. 1 seen inside the container).
  7. Memory limit enforced: inside the container, run a memory bomb (sh -c 'a=AAAA; while true; do a="$a$a"; done') — it gets OOM-killed by the cgroup, without affecting the host VM.
  8. CPU limit enforced: yes > /dev/null inside the container while watching host-side top — usage caps near the configured fraction of one core.
  9. Cleanup: after exit (or Ctrl-C mid-session), /sys/fs/cgroup/mini-run/<id> is gone.
  10. Exit code propagation: sudo ./mini-run run ./rootfs /bin/sh -c "exit 42"; echo $? prints 42.

The portable pieces (flag parsing, ID generation, memory/CPU string parsing) build and vet directly on macOS without Lima:

go build ./... && go vet ./...

About

A minimal container runtime CLI in Go: Linux namespaces, pivot_root filesystem jailing, cgroups v2 resource limits, and interactive PTY passthrough — no image management, overlayfs, or daemon.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors