A compact Go-based utility that demonstrates simple container-like behavior using Linux namespaces, cgroups and a bundled minimal root filesystem in ubuntufs/.
This README documents how the project works (using main.go and utils.go), how to build and run the program, and safe example workflows for inspecting or packaging the provided ubuntufs/ tree.
Files of interest
- main.go — the CLI and namespace/container orchestration logic
- utils.go — helpers that create cgroups, set limits and hostname
- Makefile — convenience target for building and launching a container-like process
ubuntufs/— the minimal Ubuntu-like rootfs included in the repo
High-level behavior
main.gosupports two process modes selected via the--ProcessTypeflag:--ProcessType=runstarts a parent process that re-executes the current binary with--ProcessType=childinside new namespaces.--ProcessType=childruns inside the new namespaces and performschroot("ubuntufs/"), mounts/proc, applies cgroup limits and then runs the requested command.
utils.gocreates a cgroup directory under/sys/fs/cgroup/<containerName>and writes topids.maxandmemory.maxto enforce limits.
Prerequisites & safety
- Go 1.20+ (or a compatible Go toolchain)
- Linux host with namespace and cgroup support. The code writes to
/sys/fs/cgroup/*and expects writable cgroup controllers (common with cgroup v2 or properly mounted controllers). - Root privileges are required for namespace creation, mounting, chroot, and writing cgroup limits. Run the examples with
sudoor from an account with the necessary capabilities. - This project is educational; do not use it to run untrusted code on production hosts.
Build
Build the binary with either the Makefile or go build:
go build -o main ./Or use the Makefile target:
make runThe make run target builds and then executes the binary using sudo with the following example flags defined in the Makefile:
--ProcessType=run— start the parent which spawns the namespaced child--name=container— container name used for the cgroup path--processes=20— setspids.maxfor the cgroup--memory=10485760— setsmemory.maxfor the cgroup (value in bytes)
Run (manual)
You can run the parent process directly; it will spawn a child process in new namespaces and then run the provided command inside the ubuntufs/ chroot. Example (uses sudo):
sudo ./main --ProcessType=run --name=mycontainer --processes=10 --memory=52428800 /bin/bashThis will:
- The parent process will re-exec
/proc/self/exewith--ProcessType=childand clone flags:CLONE_NEWUTS,CLONE_NEWPID,CLONE_NEWNS,CLONE_NEWNET,CLONE_NEWIPC. - The child will:
- create
/sys/fs/cgroup/<containerName>and write its PID tocgroup.procs. - write limits to
pids.maxandmemory.maxunder that cgroup path. - call
syscall.Chroot("ubuntufs/")andsyscall.Chdir("/"). - mount
procat/procand then exec the requested command (e.g.,/bin/bash).
- create
Example output
When running the child you should see a line similar to:
Running with pid 12345
And then the shell or command prompt inside the chroot.
Notes on ubuntufs/
ubuntufs/is an expanded root filesystem tree (not an image file). You can inspect it directly or use it as a chroot target as the program does.- To add binaries, libraries or configuration, copy files into the appropriate directories inside
ubuntufs/(for example add/bin/shand its required libraries intoubuntufs/binandubuntufs/librespectively).
Security & limitations
- This program does not perform full container isolation (no seccomp, no user namespaces, no sophisticated filesystem layering).
- Limitations depend on host kernel configuration and cgroup setup; test on a disposable VM if possible.
Contributing
- For code changes, update
main.goorutils.goand add small focused commits. Add unit tests where appropriate. - If you want, I can add a
--helpimplementation inmain.gothat prints usage and available flags, or provide a sampleDockerfilethat demonstrates how to incorporateubuntufs/into a Docker context.
License
- No license file is included. Add a
LICENSEif you plan to publish this repository.