$ -weight: 500;">docker run alpine echo hello
-weight: 500;">docker run alpine echo hello
-weight: 500;">docker run alpine echo hello
image resolution
filesystem preparation
namespace creation
cgroup configuration
mount setup
network setup
process execution
log tracking
metadata storage
cleanup
image resolution
filesystem preparation
namespace creation
cgroup configuration
mount setup
network setup
process execution
log tracking
metadata storage
cleanup
image resolution
filesystem preparation
namespace creation
cgroup configuration
mount setup
network setup
process execution
log tracking
metadata storage
cleanup
tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
tiny--weight: 500;">docker-go ps
tiny--weight: 500;">docker-go logs -f <container-id>
tiny--weight: 500;">docker-go -weight: 500;">stop <container-id>
tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
tiny--weight: 500;">docker-go ps
tiny--weight: 500;">docker-go logs -f <container-id>
tiny--weight: 500;">docker-go -weight: 500;">stop <container-id>
tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
tiny--weight: 500;">docker-go ps
tiny--weight: 500;">docker-go logs -f <container-id>
tiny--weight: 500;">docker-go -weight: 500;">stop <container-id>
Go can build on macOS.
Therefore, my runtime should work on macOS.
Go can build on macOS.
Therefore, my runtime should work on macOS.
Go can build on macOS.
Therefore, my runtime should work on macOS.
Go can compile the program for macOS.
But Linux container primitives still require Linux.
Go can compile the program for macOS.
But Linux container primitives still require Linux.
Go can compile the program for macOS.
But Linux container primitives still require Linux.
CLONE_NEWUTS
CLONE_NEWPID
CLONE_NEWNS
CLONE_NEWNET
cgroup filesystem
mount operations
veth networking
iptables rules
CLONE_NEWUTS
CLONE_NEWPID
CLONE_NEWNS
CLONE_NEWNET
cgroup filesystem
mount operations
veth networking
iptables rules
CLONE_NEWUTS
CLONE_NEWPID
CLONE_NEWNS
CLONE_NEWNET
cgroup filesystem
mount operations
veth networking
iptables rules
PID namespace -> gives the process its own process tree
UTS namespace -> gives the process its own hostname
mount namespace -> gives the process its own mount view
network namespace -> gives the process its own network stack
cgroups -> limit and track resource usage
chroot/rootfs -> changes the visible filesystem root
PID namespace -> gives the process its own process tree
UTS namespace -> gives the process its own hostname
mount namespace -> gives the process its own mount view
network namespace -> gives the process its own network stack
cgroups -> limit and track resource usage
chroot/rootfs -> changes the visible filesystem root
PID namespace -> gives the process its own process tree
UTS namespace -> gives the process its own hostname
mount namespace -> gives the process its own mount view
network namespace -> gives the process its own network stack
cgroups -> limit and track resource usage
chroot/rootfs -> changes the visible filesystem root
macOS -> tiny--weight: 500;">docker-go -> Linux namespaces/cgroups
macOS -> tiny--weight: 500;">docker-go -> Linux namespaces/cgroups
macOS -> tiny--weight: 500;">docker-go -> Linux namespaces/cgroups
macOS -> Linux VM -> tiny--weight: 500;">docker-go -> Linux namespaces/cgroups
macOS -> Linux VM -> tiny--weight: 500;">docker-go -> Linux namespaces/cgroups
macOS -> Linux VM -> tiny--weight: 500;">docker-go -> Linux namespaces/cgroups
Lima is not Docker.
Lima is not my container runtime.
Lima gives me a Linux VM.
Lima is not Docker.
Lima is not my container runtime.
Lima gives me a Linux VM.
Lima is not Docker.
Lima is not my container runtime.
Lima gives me a Linux VM.
MacBook └── macOS └── Lima VM └── Linux └── my tiny Docker-like runtime └── container-like process
MacBook └── macOS └── Lima VM └── Linux └── my tiny Docker-like runtime └── container-like process
MacBook └── macOS └── Lima VM └── Linux └── my tiny Docker-like runtime └── container-like process
How do I run an app in Docker?
How do I run an app in Docker?
How do I run an app in Docker?
How does a container runtime use Linux features to isolate a process?
How does a container runtime use Linux features to isolate a process?
How does a container runtime use Linux features to isolate a process?
Docker Desktop: Great for running Docker containers and application stacks. Lima: Great for getting a Linux environment on macOS and experimenting with Linux internals.
Docker Desktop: Great for running Docker containers and application stacks. Lima: Great for getting a Linux environment on macOS and experimenting with Linux internals.
Docker Desktop: Great for running Docker containers and application stacks. Lima: Great for getting a Linux environment on macOS and experimenting with Linux internals.
-weight: 500;">brew -weight: 500;">install lima
-weight: 500;">brew -weight: 500;">install lima
-weight: 500;">brew -weight: 500;">install lima
limactl -weight: 500;">start --name=tiny--weight: 500;">docker --cpus=4 --memory=4 --disk=20
limactl -weight: 500;">start --name=tiny--weight: 500;">docker --cpus=4 --memory=4 --disk=20
limactl -weight: 500;">start --name=tiny--weight: 500;">docker --cpus=4 --memory=4 --disk=20
limactl shell tiny--weight: 500;">docker
limactl shell tiny--weight: 500;">docker
limactl shell tiny--weight: 500;">docker
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">update
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -y golang-go -weight: 500;">curl tar iproute2 iptables
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">update
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -y golang-go -weight: 500;">curl tar iproute2 iptables
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">update
-weight: 600;">sudo -weight: 500;">apt -weight: 500;">install -y golang-go -weight: 500;">curl tar iproute2 iptables
golang-go -> build and test the runtime
-weight: 500;">curl -> download rootfs archives
tar -> extract rootfs archives
iproute2 -> work with Linux networking
iptables -> configure NAT for isolated networking
golang-go -> build and test the runtime
-weight: 500;">curl -> download rootfs archives
tar -> extract rootfs archives
iproute2 -> work with Linux networking
iptables -> configure NAT for isolated networking
golang-go -> build and test the runtime
-weight: 500;">curl -> download rootfs archives
tar -> extract rootfs archives
iproute2 -> work with Linux networking
iptables -> configure NAT for isolated networking
mkdir -p rootfs/alpine ARCH=$(uname -m) -weight: 500;">curl -L -o alpine-rootfs.tar.gz \ "https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/${ARCH}/alpine-minirootfs-3.23.4-${ARCH}.tar.gz" -weight: 600;">sudo tar -xzf alpine-rootfs.tar.gz -C rootfs/alpine
mkdir -p rootfs/alpine ARCH=$(uname -m) -weight: 500;">curl -L -o alpine-rootfs.tar.gz \ "https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/${ARCH}/alpine-minirootfs-3.23.4-${ARCH}.tar.gz" -weight: 600;">sudo tar -xzf alpine-rootfs.tar.gz -C rootfs/alpine
mkdir -p rootfs/alpine ARCH=$(uname -m) -weight: 500;">curl -L -o alpine-rootfs.tar.gz \ "https://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/${ARCH}/alpine-minirootfs-3.23.4-${ARCH}.tar.gz" -weight: 600;">sudo tar -xzf alpine-rootfs.tar.gz -C rootfs/alpine
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
Docker image: A packaged filesystem with metadata and layers. Rootfs: The actual filesystem view used by the container process.
Docker image: A packaged filesystem with metadata and layers. Rootfs: The actual filesystem view used by the container process.
Docker image: A packaged filesystem with metadata and layers. Rootfs: The actual filesystem view used by the container process.
If host is Linux: run the runtime directly. If host is macOS: route the command through Lima. execute the Linux binary inside the Lima VM.
If host is Linux: run the runtime directly. If host is macOS: route the command through Lima. execute the Linux binary inside the Lima VM.
If host is Linux: run the runtime directly. If host is macOS: route the command through Lima. execute the Linux binary inside the Lima VM.
tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
limactl shell tiny--weight: 500;">docker -weight: 600;">sudo ./bin/tiny--weight: 500;">docker-go-linux-amd64 \ run \ --rootfs ./rootfs/alpine \ /bin/sh
limactl shell tiny--weight: 500;">docker -weight: 600;">sudo ./bin/tiny--weight: 500;">docker-go-linux-amd64 \ run \ --rootfs ./rootfs/alpine \ /bin/sh
limactl shell tiny--weight: 500;">docker -weight: 600;">sudo ./bin/tiny--weight: 500;">docker-go-linux-amd64 \ run \ --rootfs ./rootfs/alpine \ /bin/sh
macOS terminal | | tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh v
Darwin -weight: 500;">service layer | | limactl shell tiny--weight: 500;">docker -weight: 600;">sudo Linux binary ... v
Lima VM | v
Linux runtime binary | v
namespaces + cgroups + chroot + networking
macOS terminal | | tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh v
Darwin -weight: 500;">service layer | | limactl shell tiny--weight: 500;">docker -weight: 600;">sudo Linux binary ... v
Lima VM | v
Linux runtime binary | v
namespaces + cgroups + chroot + networking
macOS terminal | | tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh v
Darwin -weight: 500;">service layer | | limactl shell tiny--weight: 500;">docker -weight: 600;">sudo Linux binary ... v
Lima VM | v
Linux runtime binary | v
namespaces + cgroups + chroot + networking
mkdir -p bin GOOS=linux GOARCH=amd64 \ go build -o bin/tiny--weight: 500;">docker-go-linux-amd64 ./cmd/tiny--weight: 500;">docker-go
mkdir -p bin GOOS=linux GOARCH=amd64 \ go build -o bin/tiny--weight: 500;">docker-go-linux-amd64 ./cmd/tiny--weight: 500;">docker-go
mkdir -p bin GOOS=linux GOARCH=amd64 \ go build -o bin/tiny--weight: 500;">docker-go-linux-amd64 ./cmd/tiny--weight: 500;">docker-go
mkdir -p bin GOOS=linux GOARCH=arm64 \ go build -o bin/tiny--weight: 500;">docker-go-linux-arm64 ./cmd/tiny--weight: 500;">docker-go
mkdir -p bin GOOS=linux GOARCH=arm64 \ go build -o bin/tiny--weight: 500;">docker-go-linux-arm64 ./cmd/tiny--weight: 500;">docker-go
mkdir -p bin GOOS=linux GOARCH=arm64 \ go build -o bin/tiny--weight: 500;">docker-go-linux-arm64 ./cmd/tiny--weight: 500;">docker-go
limactl shell tiny--weight: 500;">docker uname -m
limactl shell tiny--weight: 500;">docker uname -m
limactl shell tiny--weight: 500;">docker uname -m
x86_64 -> GOARCH=amd64
aarch64 -> GOARCH=arm64
x86_64 -> GOARCH=amd64
aarch64 -> GOARCH=arm64
x86_64 -> GOARCH=amd64
aarch64 -> GOARCH=arm64
exec format error
exec format error
exec format error
The binary architecture does not match the machine trying to execute it.
The binary architecture does not match the machine trying to execute it.
The binary architecture does not match the machine trying to execute it.
/Users/amir/Desktop/tiny--weight: 500;">docker
/Users/amir/Desktop/tiny--weight: 500;">docker
/Users/amir/Desktop/tiny--weight: 500;">docker
cd /Users/amir/Desktop/tiny--weight: 500;">docker
cd /Users/amir/Desktop/tiny--weight: 500;">docker
cd /Users/amir/Desktop/tiny--weight: 500;">docker
No such file or directory
No such file or directory
No such file or directory
limactl shell tiny--weight: 500;">docker pwd
limactl shell tiny--weight: 500;">docker ls -la /Users
limactl shell tiny--weight: 500;">docker ls -la /Users/amir/Desktop
limactl shell tiny--weight: 500;">docker pwd
limactl shell tiny--weight: 500;">docker ls -la /Users
limactl shell tiny--weight: 500;">docker ls -la /Users/amir/Desktop
limactl shell tiny--weight: 500;">docker pwd
limactl shell tiny--weight: 500;">docker ls -la /Users
limactl shell tiny--weight: 500;">docker ls -la /Users/amir/Desktop
-weight: 500;">git clone <your-repo-url>
cd tiny--weight: 500;">docker
-weight: 500;">git clone <your-repo-url>
cd tiny--weight: 500;">docker
-weight: 500;">git clone <your-repo-url>
cd tiny--weight: 500;">docker
./tiny--weight: 500;">docker-go
./bin/tiny--weight: 500;">docker-go-linux-amd64
./bin/tiny--weight: 500;">docker-go-linux-arm64
./tiny--weight: 500;">docker-go
./bin/tiny--weight: 500;">docker-go-linux-amd64
./bin/tiny--weight: 500;">docker-go-linux-arm64
./tiny--weight: 500;">docker-go
./bin/tiny--weight: 500;">docker-go-linux-amd64
./bin/tiny--weight: 500;">docker-go-linux-arm64
macOS binary: command parsing platform detection Lima dispatching Linux binary: namespaces cgroups chroot mount setup networking process lifecycle
macOS binary: command parsing platform detection Lima dispatching Linux binary: namespaces cgroups chroot mount setup networking process lifecycle
macOS binary: command parsing platform detection Lima dispatching Linux binary: namespaces cgroups chroot mount setup networking process lifecycle
limactl is not installed
Lima instance does not exist
Lima instance is not running
Linux binary is missing
Rootfs is not accessible inside Lima
limactl is not installed
Lima instance does not exist
Lima instance is not running
Linux binary is missing
Rootfs is not accessible inside Lima
limactl is not installed
Lima instance does not exist
Lima instance is not running
Linux binary is missing
Rootfs is not accessible inside Lima
Is limactl installed?
Does the Lima instance exist?
Is the Lima instance running?
Does the Linux binary exist?
Is the Linux binary accessible inside Lima?
Is the rootfs path accessible inside Lima?
Is limactl installed?
Does the Lima instance exist?
Is the Lima instance running?
Does the Linux binary exist?
Is the Linux binary accessible inside Lima?
Is the rootfs path accessible inside Lima?
Is limactl installed?
Does the Lima instance exist?
Is the Lima instance running?
Does the Linux binary exist?
Is the Linux binary accessible inside Lima?
Is the rootfs path accessible inside Lima?
Linux binary not found at "./bin/tiny--weight: 500;">docker-go-linux-amd64";
build it first and share it with Lima.
Linux binary not found at "./bin/tiny--weight: 500;">docker-go-linux-amd64";
build it first and share it with Lima.
Linux binary not found at "./bin/tiny--weight: 500;">docker-go-linux-amd64";
build it first and share it with Lima.
rootfs "./rootfs/alpine" is not accessible inside Lima;
ensure the workspace is shared with the VM.
rootfs "./rootfs/alpine" is not accessible inside Lima;
ensure the workspace is shared with the VM.
rootfs "./rootfs/alpine" is not accessible inside Lima;
ensure the workspace is shared with the VM.
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/sh
cat /etc/os-release
cat /etc/os-release
cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.23.4
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.23.4
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.23.4
-weight: 600;">sudo ./tiny--weight: 500;">docker-go ps
-weight: 600;">sudo ./tiny--weight: 500;">docker-go ps
-weight: 600;">sudo ./tiny--weight: 500;">docker-go ps
ID STATUS PID CREATED COMMAND
ab12cd34ef56 running 1234 2026-05-17 12:30:45 /bin/sh
ID STATUS PID CREATED COMMAND
ab12cd34ef56 running 1234 2026-05-17 12:30:45 /bin/sh
ID STATUS PID CREATED COMMAND
ab12cd34ef56 running 1234 2026-05-17 12:30:45 /bin/sh
./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/echo "hello from linux"
./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/echo "hello from linux"
./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/echo "hello from linux"
limactl shell tiny--weight: 500;">docker -weight: 600;">sudo ./bin/tiny--weight: 500;">docker-go-linux-amd64 \ run \ --rootfs ./rootfs/alpine \ /bin/echo "hello from linux"
limactl shell tiny--weight: 500;">docker -weight: 600;">sudo ./bin/tiny--weight: 500;">docker-go-linux-amd64 \ run \ --rootfs ./rootfs/alpine \ /bin/echo "hello from linux"
limactl shell tiny--weight: 500;">docker -weight: 600;">sudo ./bin/tiny--weight: 500;">docker-go-linux-amd64 \ run \ --rootfs ./rootfs/alpine \ /bin/echo "hello from linux"
hello from linux
hello from linux
hello from linux
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run \ --memory 128m \ --rootfs ./rootfs/alpine \ /bin/sh
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run \ --memory 128m \ --rootfs ./rootfs/alpine \ /bin/sh
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run \ --memory 128m \ --rootfs ./rootfs/alpine \ /bin/sh
cat /sys/fs/cgroup/memory.max
cat /sys/fs/cgroup/memory.max
cat /sys/fs/cgroup/memory.max
-weight: 500;">docker run --memory 128m alpine
-weight: 500;">docker run --memory 128m alpine
-weight: 500;">docker run --memory 128m alpine
Docker exposes a nice option.
The Linux kernel enforces the limit through cgroups.
Docker exposes a nice option.
The Linux kernel enforces the limit through cgroups.
Docker exposes a nice option.
The Linux kernel enforces the limit through cgroups.
host bridge | veth pair |
container network namespace
host bridge | veth pair |
container network namespace
host bridge | veth pair |
container network namespace
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run \ --net isolated \ --rootfs ./rootfs/alpine \ /bin/sh
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run \ --net isolated \ --rootfs ./rootfs/alpine \ /bin/sh
-weight: 600;">sudo ./tiny--weight: 500;">docker-go run \ --net isolated \ --rootfs ./rootfs/alpine \ /bin/sh
ip addr
ip route
ip addr
ip route
ip addr
ip route
-weight: 500;">docker run nginx
-weight: 500;">docker run nginx
-weight: 500;">docker run nginx
network namespaces
veth pairs
bridges
routes
iptables
NAT
network namespaces
veth pairs
bridges
routes
iptables
NAT
network namespaces
veth pairs
bridges
routes
iptables
NAT
Before:
/ After:
./rootfs/alpine becomes /
Before:
/ After:
./rootfs/alpine becomes /
Before:
/ After:
./rootfs/alpine becomes /
pivot_root
overlay filesystems
image layers
OCI runtime spec
capability dropping
seccomp
AppArmor
SELinux
user namespaces
read-only mounts
masked paths
pivot_root
overlay filesystems
image layers
OCI runtime spec
capability dropping
seccomp
AppArmor
SELinux
user namespaces
read-only mounts
masked paths
pivot_root
overlay filesystems
image layers
OCI runtime spec
capability dropping
seccomp
AppArmor
SELinux
user namespaces
read-only mounts
masked paths
This is a tiny educational runtime.
It demonstrates some basic container building blocks.
It is not a production replacement for Docker, containerd, or runc.
This is a tiny educational runtime.
It demonstrates some basic container building blocks.
It is not a production replacement for Docker, containerd, or runc.
This is a tiny educational runtime.
It demonstrates some basic container building blocks.
It is not a production replacement for Docker, containerd, or runc.
-weight: 500;">docker build
-weight: 500;">docker run
-weight: 500;">docker ps
-weight: 500;">docker logs
-weight: 500;">docker -weight: 500;">stop
-weight: 500;">docker build
-weight: 500;">docker run
-weight: 500;">docker ps
-weight: 500;">docker logs
-weight: 500;">docker -weight: 500;">stop
-weight: 500;">docker build
-weight: 500;">docker run
-weight: 500;">docker ps
-weight: 500;">docker logs
-weight: 500;">docker -weight: 500;">stop
Docker CLI
Docker daemon
containerd
runc
Linux namespaces
Linux cgroups
root filesystem
network namespace
mount namespace
process lifecycle
Docker CLI
Docker daemon
containerd
runc
Linux namespaces
Linux cgroups
root filesystem
network namespace
mount namespace
process lifecycle
Docker CLI
Docker daemon
containerd
runc
Linux namespaces
Linux cgroups
root filesystem
network namespace
mount namespace
process lifecycle
-weight: 500;">docker run alpine echo hello
-weight: 500;">docker run alpine echo hello
-weight: 500;">docker run alpine echo hello
resolving the image
downloading layers
preparing the root filesystem
creating namespaces
configuring cgroups
setting up mounts
configuring networking
starting the process
attaching stdio
tracking metadata
collecting exit -weight: 500;">status
cleaning up resources
resolving the image
downloading layers
preparing the root filesystem
creating namespaces
configuring cgroups
setting up mounts
configuring networking
starting the process
attaching stdio
tracking metadata
collecting exit -weight: 500;">status
cleaning up resources
resolving the image
downloading layers
preparing the root filesystem
creating namespaces
configuring cgroups
setting up mounts
configuring networking
starting the process
attaching stdio
tracking metadata
collecting exit -weight: 500;">status
cleaning up resources
Docker CLI
Docker Compose
image management
container lifecycle management
volume support
networking
developer-friendly tooling
Docker CLI
Docker Compose
image management
container lifecycle management
volume support
networking
developer-friendly tooling
Docker CLI
Docker Compose
image management
container lifecycle management
volume support
networking
developer-friendly tooling
a Linux VM
direct access to Linux tools
a clean environment for experiments
less abstraction around Docker itself
a Linux VM
direct access to Linux tools
a clean environment for experiments
less abstraction around Docker itself
a Linux VM
direct access to Linux tools
a clean environment for experiments
less abstraction around Docker itself
Use Docker Desktop when your goal is to run and ship applications.
Use Lima when your goal is to understand or control the Linux environment.
Use Docker Desktop when your goal is to run and ship applications.
Use Lima when your goal is to understand or control the Linux environment.
Use Docker Desktop when your goal is to run and ship applications.
Use Lima when your goal is to understand or control the Linux environment.
/bin/echo hello
/bin/echo hello
/bin/echo hello
time -weight: 600;">sudo ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/echo hello
time -weight: 600;">sudo ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/echo hello
time -weight: 600;">sudo ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/echo hello
hello real 0m0.045s
user 0m0.008s
sys 0m0.020s
hello real 0m0.045s
user 0m0.008s
sys 0m0.020s
hello real 0m0.045s
user 0m0.008s
sys 0m0.020s
time ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/echo hello
time ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/echo hello
time ./tiny--weight: 500;">docker-go run --rootfs ./rootfs/alpine /bin/echo hello
limactl shell tiny--weight: 500;">docker -weight: 600;">sudo ./bin/tiny--weight: 500;">docker-go-linux-amd64 \ run \ --rootfs ./rootfs/alpine \ /bin/echo hello
limactl shell tiny--weight: 500;">docker -weight: 600;">sudo ./bin/tiny--weight: 500;">docker-go-linux-amd64 \ run \ --rootfs ./rootfs/alpine \ /bin/echo hello
limactl shell tiny--weight: 500;">docker -weight: 600;">sudo ./bin/tiny--weight: 500;">docker-go-linux-amd64 \ run \ --rootfs ./rootfs/alpine \ /bin/echo hello
hello real 0m0.180s
user 0m0.020s
sys 0m0.030s
hello real 0m0.180s
user 0m0.020s
sys 0m0.030s
hello real 0m0.180s
user 0m0.020s
sys 0m0.030s
Direct inside Lima: ~45 ms
macOS through Lima: ~180 ms
Extra routing overhead: ~135 ms
Direct inside Lima: ~45 ms
macOS through Lima: ~180 ms
Extra routing overhead: ~135 ms
Direct inside Lima: ~45 ms
macOS through Lima: ~180 ms
Extra routing overhead: ~135 ms
For a nice macOS developer experience, routing through Lima is acceptable.
For tight benchmark loops, run directly inside the VM.
For production-grade runtimes, this approach is educational, not final.
For a nice macOS developer experience, routing through Lima is acceptable.
For tight benchmark loops, run directly inside the VM.
For production-grade runtimes, this approach is educational, not final.
For a nice macOS developer experience, routing through Lima is acceptable.
For tight benchmark loops, run directly inside the VM.
For production-grade runtimes, this approach is educational, not final.
use pivot_root instead of only chroot
improve cgroup v2 handling
support better cleanup
add more robust metadata storage
improve log streaming
support better TTY handling
add user namespace support
drop Linux capabilities
add seccomp profiles
use pivot_root instead of only chroot
improve cgroup v2 handling
support better cleanup
add more robust metadata storage
improve log streaming
support better TTY handling
add user namespace support
drop Linux capabilities
add seccomp profiles
use pivot_root instead of only chroot
improve cgroup v2 handling
support better cleanup
add more robust metadata storage
improve log streaming
support better TTY handling
add user namespace support
drop Linux capabilities
add seccomp profiles
detect Lima architecture automatically
choose the correct Linux binary automatically
improve Lima instance setup
validate shared paths more clearly
provide a bootstrap command for macOS users
make error messages more actionable
detect Lima architecture automatically
choose the correct Linux binary automatically
improve Lima instance setup
validate shared paths more clearly
provide a bootstrap command for macOS users
make error messages more actionable
detect Lima architecture automatically
choose the correct Linux binary automatically
improve Lima instance setup
validate shared paths more clearly
provide a bootstrap command for macOS users
make error messages more actionable
tiny--weight: 500;">docker-go setup lima
tiny--weight: 500;">docker-go setup lima
tiny--weight: 500;">docker-go setup lima
checking limactl
creating the Lima instance
building the Linux binary
preparing the rootfs
validating mounts
testing a hello-world container
checking limactl
creating the Lima instance
building the Linux binary
preparing the rootfs
validating mounts
testing a hello-world container
checking limactl
creating the Lima instance
building the Linux binary
preparing the rootfs
validating mounts
testing a hello-world container
macOS is my workstation.
Lima gives me a Linux VM.
The Linux VM gives me namespaces and cgroups.
My Go runtime uses those Linux features.
The rootfs gives the process its filesystem.
macOS is my workstation.
Lima gives me a Linux VM.
The Linux VM gives me namespaces and cgroups.
My Go runtime uses those Linux features.
The rootfs gives the process its filesystem.
macOS is my workstation.
Lima gives me a Linux VM.
The Linux VM gives me namespaces and cgroups.
My Go runtime uses those Linux features.
The rootfs gives the process its filesystem.
-weight: 500;">docker run alpine echo hello
-weight: 500;">docker run alpine echo hello
-weight: 500;">docker run alpine echo hello - Linux namespaces
- mount isolation
- process isolation
- bridge networking
- iptables/NAT