An experimental Linux container runtime, implementing the OCI Runtime Spec.
This is a personal project for me to explore and better understand the OCI Runtime Spec. It's not production-ready, and it probably never will be, but feel free to look around! If you're looking for a production-ready alternative to runc
, take a look at youki
, which I think is pretty cool.
brownie
passes all passable tests in the opencontainers OCI runtime test suite. That doesn't mean that brownie
is feature-complete...yet. See below for outstanding items.
ποΈ To do (items remaining for me to consider this 'complete')
-
Unit testsIntegration tests seem to be sufficing - Implement optional Seccomp
- Implement optional AppArmor
- Refactor and tidy-up
Caution
Some features may require sudo
and make changes to your system.
Given this is an experimental project, take appropriate precautions.
- Go to Releases and download the tarball for your architecture, e.g.
brownie_0.0.1_linux_amd64.tar.gz
. - Extract the
brownie
binary from the tarball and put somewhere in$PATH
, e.g.~/.local/bin
.
Prerequisite: Compiler for Go installed (instructions).
git clone git@github.com:nixpig/brownie.git
cd brownie
make build
mv tmp/bin/brownie ~/.local/bin
I'm developing brownie
on the following environment. Even with the same set up, YMMV.
Linux vagrant 6.8.0-31-generic #31-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 20 00:40:06 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
go version go1.23.4 linux/amd64
Docker version 27.3.1, build ce12230
You can spin up this VM from the included Vagrantfile
, just run vagrant up
.
By default, the Docker daemon uses the runc
container runtime. brownie
can be used as a drop-in replacement for runc
.
You can find detailed instructions on how to configure alternative runtimes in the Docker docs. If you just want to quickly experiment, the following should suffice:
# 1. Stop any running Docker service
sudo systemctl stop docker.service
# 2. Start the Docker Daemon with added brownie runtime
sudo dockerd --add-runtime brownie=PATH_TO_BROWNIE_BINARY
# 3. Run a container using the brownie runtime
docker run -it --runtime brownie busybox sh
The brownie
CLI implements the OCI Runtime Command Line Interface spec.
Create a new container.
Usage:
brownie create [flags] CONTAINER_ID
Examples:
brownie create busybox
Flags:
-b, --bundle string Path to bundle directory
-s, --console-socket string Console socket
-h, --help help for create
-p, --pid-file string File to write container PID to
Start an existing container.
Usage:
brownie start [flags] CONTAINER_ID
Examples:
brownie start busybox
Flags:
-h, --help help for start
Send a signal to a running container.
Usage:
brownie kill [flags] CONTAINER_ID SIGNAL
Examples:
brownie kill busybox 9
Flags:
-h, --help help for kill
Delete a container.
Usage:
brownie delete [flags] CONTAINER_ID
Examples:
brownie delete busybox
Flags:
-f, --force force delete
-h, --help help for delete
Get the state of a container.
Usage:
brownie state [flags] CONTAINER_ID
Examples:
brownie state busybox
Flags:
-h, --help help for state
The container
package of brownie
can be used directly as a library (in the same way that the CLI does).
The consumer will be responsible for all of the necessary 'bookkeeping'.
go get github.com/nixpig/brownie/container
package main
import "github.com/nixpig/brownie/container"
func main() {
// TODO: example usage
}
My goal is for brownie
to (eventually) pass all tests in the opencontainers OCI Runtime Spec tests. Below is progress against that goal.
Tests are run on every build in this Github Action.
- default
- ___
- config_updates_without_affect
- create
- delete
- hooks
- hooks_stdin
- hostname
- kill
- killsig
- kill_no_effect
- linux_devices
- linux_masked_paths
- linux_mount_label
- linux_ns_itype
- linux_ns_nopath
- linux_ns_path
- linux_ns_path_type
- linux_readonly_paths
- linux_rootfs_propagation
- linux_sysctl
- misc_props (flaky due to test suite trying to delete container before process has exiting and status updated to stopped)
- mounts
- poststart
- poststop
- prestart
- prestart_fail
- process
- process_capabilities
- process_capabilities_fail
- process_oom_score_adj
- β process_rlimits
- process_rlimits_fail
- process_user
- root_readonly_true
- start
- state
- linux_uid_mappings
The OCI Runtime Spec test suite provided by opencontainers does not support cgroup v2.
The OCI Runtime Spec test suite provided by opencontainers does support cgroup v1.
brownie
currently implements both cgroup v1 and v2. However, like runc
and other container runtimes, the find x cgroup
tests pass and the get x cgroup data
tests fail.
Full list of cgroups tests
-
linux_cgroups_blkio -
linux_cgroups_cpus -
linux_cgroups_devices -
linux_cgroups_hugetlb -
linux_cgroups_memory -
linux_cgroups_network -
linux_cgroups_pids -
linux_cgroups_relative_blkio -
linux_cgroups_relative_cpus -
linux_cgroups_relative_devices -
linux_cgroups_relative_hugetlb -
linux_cgroups_relative_memory -
linux_cgroups_relative_network -
linux_cgroups_relative_pids -
delete_resources -
delete_only_create_resources
Tests failed by runc
and other container runtimes. In some cases the tests may be broken; in others, who knows. Either way, for my purposes, parity with other runtimes is more important than passing the tests.
-
pidfile -
poststart_fail -
poststop_fail
Tests that 'pass' (seemingly) regardless of whether the feature has been implemented. May indicate a bad test.
-
linux_process_apparmor_profile -
linux_seccomp
Given this is an exploratory personal project, I'm not interested in taking code contributions. However, if you have any comments/suggestions/feedback, do feel free to leave them in issues.
While this project was built entirely from scratch, inspiration was taken from existing runtimes, in no particular order: