A minimal, educational Docker-like container runtime implementation from scratch, focused on demonstrating container internals, monitoring capabilities, and Kubernetes integration.
This is a teaching/runtime prototype designed for:
- Understanding container isolation mechanisms
- Demonstrating the Docker monitoring problem
- Exploring Kubernetes custom resource integration
- Learning container runtime internals
Not intended for production use. This is a reference implementation for education and research.
- Container lifecycle management with state tracking (
created,running,exited,failed) - Automatic cgroup v1/v2 detection and graceful degradation
- Filesystem isolation with layered image support
- Process and network namespace isolation (when available)
- Container logs and metadata persistence
- Multi-level monitoring (process, container, host)
- Gap analysis between isolation levels
- Correlation tracking across monitoring layers
- See MONITORING.md for details
- ResourceCapsule CRD for enhanced resource modeling
- Operator for CRD reconciliation
- GitOps-compatible resource management
- See KUBERNETES_INTEGRATION.md for details
- Linux system (tested on Ubuntu 20.04+)
- Go 1.24+ for building
- Root privileges for namespace operations
- Optional: Kubernetes cluster for CRD features
go build -o basic-docker .
./basic-docker infoExpected output:
Environment detected: inContainer=false, hasNamespacePrivileges=true, hasCgroupAccess=true, cgroupVersion=2
Lean Docker Engine - System Information
=======================================
Go version: go1.24.11
OS/Arch: linux/amd64
Running in container: false
Namespace privileges: true
Cgroup access: true
Cgroup version: v2
Cgroup base path: /sys/fs/cgroup
Memory controller: true
CPU controller: true
Available features:
- Process isolation: true
- Network isolation: true
- Resource limits (memory): true
- Resource limits (CPU): true
- Filesystem isolation: true
sudo mkdir -p /tmp/basic-docker/containers
sudo mkdir -p /tmp/basic-docker/images
sudo mkdir -p /sys/fs/cgroup/memory/basic-dockersudo chmod -R 755 /tmp/basic-docker# Run a simple command
sudo ./basic-docker run test-image /bin/echo "Hello from container"
# Run an interactive shell (requires image with /bin/sh)
sudo ./basic-docker run test-image /bin/sh# Shows all containers with their states
sudo ./basic-docker psExample output:
CONTAINER ID STATE COMMAND CREATED
container-1767175530 exited /bin/echo 2025-12-31 10:05:30
container-1767175600 running /bin/sleep 2025-12-31 10:06:00
# Get detailed container information in JSON format
sudo ./basic-docker inspect <container-id>Example output:
{
"id": "container-1767175530",
"state": "exited",
"image": "test-image",
"command": "/bin/echo",
"args": ["Hello from container"],
"created_at": "2025-12-31T10:05:30Z",
"started_at": "2025-12-31T10:05:30Z",
"finished_at": "2025-12-31T10:05:30Z",
"exit_code": 0,
"pid": 7505,
"rootfs_path": "/tmp/basic-docker/containers/container-1767175530/rootfs"
}# Display stdout/stderr from a container
sudo ./basic-docker logs <container-id># Clean up container directories and resources
sudo ./basic-docker rm <container-id>Note: Cannot remove running containers. Stop them first.
# Display system capabilities and cgroup information
./basic-docker infoThis command shows:
- Cgroup version (v1 or v2) and availability
- Memory and CPU controller support
- Namespace privileges
- Available isolation features
flowchart TB
subgraph "Basic Docker Engine"
CLI[CLI Interface]
ENV[Environment Detection]
CMD[Command Handler]
subgraph "Container Runtime"
EXEC[Container Execution]
FS[Filesystem Manager]
NET[Network Manager]
RES[Resource Controller]
end
subgraph "Image Management"
IMG[Image Store]
PULL[Image Puller]
end
subgraph "Isolation Components"
FULL["Full Isolation\n(Linux Namespaces)"]
LIMITED["Limited Isolation\n(chroot/unshare)"]
FALLBACK["Minimal Isolation\n(runWithoutNamespaces)"]
end
end
subgraph "Environment Detection"
DETECT{Environment?}
PRIV{Privileges?}
CGROUP{CGroup Access?}
end
subgraph "Host System"
LINUX[Linux Kernel]
CONTAINERS[Container Environment]
end
%% Main flow
CLI --> CMD
CMD --> ENV
ENV --> DETECT
%% Environment detection flow
DETECT -->|"Pure Linux"| PRIV
DETECT -->|"Container"| LIMITED
PRIV -->|"Root"| FULL
PRIV -->|"Non-root"| LIMITED
ENV --> CGROUP
CGROUP -->|"Yes"| RES
CGROUP -->|"No"| EXEC
%% Execution paths
FULL --> EXEC
LIMITED --> EXEC
FALLBACK --> EXEC
%% Container runtime components
EXEC --> FS
EXEC -.-> NET
EXEC -.-> RES
%% Image management
CMD -.-> IMG
IMG -.-> PULL
PULL -.-> FS
%% Host system interactions
FULL --> LINUX
LIMITED --> CONTAINERS
FALLBACK --> CONTAINERS
%% Styling
classDef primary fill:#d0e0ff,stroke:#3080ff,stroke-width:2px
classDef secondary fill:#ffe0d0,stroke:#ff8030,stroke-width:2px
classDef tertiary fill:#d0ffe0,stroke:#30ff80,stroke-width:2px
classDef highlight fill:#ffff80,stroke:#808000,stroke-width:2px
class CLI,CMD,ENV primary
class EXEC,FS,NET,RES secondary
class FULL,LIMITED,FALLBACK tertiary
class DETECT,PRIV,CGROUP highlight
Containers follow a well-defined state model:
created → running → exited
↓
failed
- created: Container directory structure created, metadata initialized
- running: Container process is executing
- exited: Container completed successfully (exit code 0)
- failed: Container terminated with error (non-zero exit code)
Container state is stored in /tmp/basic-docker/containers/<id>/state.json:
{
"id": "container-123",
"state": "exited",
"image": "alpine",
"command": "/bin/echo",
"args": ["hello"],
"created_at": "2025-12-31T10:00:00Z",
"started_at": "2025-12-31T10:00:01Z",
"finished_at": "2025-12-31T10:00:02Z",
"exit_code": 0,
"pid": 12345,
"rootfs_path": "/tmp/basic-docker/containers/container-123/rootfs"
}The runtime automatically detects and adapts to the available cgroup version:
- Detected via
/sys/fs/cgroup/cgroup.controllers - Uses
memory.maxfor memory limits - Controllers enabled via
cgroup.subtree_control
- Detected via
/sys/fs/cgroup/memorysubsystem - Uses
memory.limit_in_bytesfor memory limits - Separate hierarchy per resource type
When cgroup access is not available or permissions are insufficient:
- Container still runs without resource limits
- Warning logged but execution continues
infocommand shows cgroup availability status- No fatal errors from missing cgroup support
This ensures the runtime works in various environments (containers, VMs, bare metal) without requiring cgroup permissions.
graph TD
A[Start] --> B[Check if Base Layer Exists]
B -->|Yes| C[Load Base Layer Metadata]
B -->|No| D[Create Base Layer]
D --> E[Initialize Base Layer with Minimal Rootfs]
E --> F[Save Base Layer Metadata]
C --> G[Create App Layer]
G --> H[Add Container-Specific Files to App Layer]
H --> I[Save App Layer Metadata]
F --> G
I --> J[Mount Layers to Create Rootfs]
J --> K[Run Container with Rootfs]
K --> L[End]
%% Styling
classDef startEnd fill:#d0e0ff,stroke:#3080ff,stroke-width:2px
classDef process fill:#ffe0d0,stroke:#ff8030,stroke-width:2px
classDef decision fill:#d0ffe0,stroke:#30ff80,stroke-width:2px
class A,L startEnd
class B decision
class C,D,E,F,G,H,I,J,K process
The logic implemented for building images and running containers in the basic Docker engine. It starts by checking if the base layer exists, initializes it if necessary, and then creates an app layer for container-specific files. Finally, the layers are mounted to create the root filesystem, and the container is executed.
graph TD
subgraph Image Management
Image["Image"]
Registry["Registry Interface"]
Manifest["Manifest"]
Pull["Pull Function"]
ListImages["ListImages Function"]
ExtractLayer["extractLayer Function"]
end
subgraph Main Application
Main["main Function"]
ListContainers["listContainers Function"]
Run["run Function"]
PrintSystemInfo["printSystemInfo Function"]
ExecCommand["execCommand Function"]
end
Main -->|Delegates| Pull
Main -->|Delegates| ListImages
Pull -->|Uses| Registry
Pull -->|Uses| Manifest
Pull -->|Calls| ExtractLayer
ListImages -->|Reads| Image
Run -->|Creates| Image
ExecCommand -->|Interacts| Containers
This diagram provides an overview of the key classes and functions in the project, showing their relationships and responsibilities.
The basic-docker engine now includes comprehensive monitoring capabilities that address the "Docker monitoring problem" by providing visibility across process, container, and host isolation levels.
# Monitor host-level metrics
./basic-docker monitor host
# Monitor specific process
./basic-docker monitor process <PID>
# Monitor specific container
./basic-docker monitor container <container-id>
# Monitor all levels (process, container, host)
./basic-docker monitor all
# Analyze monitoring gaps between isolation levels
./basic-docker monitor gap
# Show correlation between monitoring levels
./basic-docker monitor correlation <container-id>./basic-docker monitor correlation container-1234Shows the correlation table as described in the Docker monitoring problem:
| Aspect | Process | Container | Host |
|---|---|---|---|
| Spec | Source | Dockerfile | Kickstart |
| On disk | .TEXT | /var/lib/docker | / |
| In memory | PID | Container ID | Hostname |
| In network | Socket | veth* | eth* |
| Runtime context | server core | host | data center |
| Isolation | moderate | private OS view | full |
See MONITORING.md for detailed documentation.
/workspaces/basic-docker-engine (main) $ ./basic-docker info
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=false
Lean Docker Engine - System Information
=======================================
Go version: go1.24.1
OS/Arch: linux/amd64
Running in container: true
Namespace privileges: true
Cgroup access: false
Available features:
- Process isolation: true
- Network isolation: true
- Resource limits: false
- Filesystem isolation: true/workspaces/basic-docker-engine (main) $ ./basic-docker run /bin/echo "Hello from container"
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=false
Starting container container-1743307284
unshare: unshare failed: Operation not permitted
Error: exit status 1
Container container-1743307284 exited
@j143 ➜ /workspaces/basic-docker-engine (main) $ sudo ./basic-docker run /bin/echo "Hello from container"
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=true
Starting container container-1743307290
Hello from container
Container container-1743307290 exited@j143 ➜ /workspaces/basic-docker-engine (main) $ sudo ./basic-docker ps
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=true
CONTAINER ID STATUS COMMAND
container-1743307284 N/A N/A
container-1743307290 N/A N/A@j143 ➜ /workspaces/basic-docker-engine (main) $ sudo ./basic-docker run /bin/echo "Hello from container"
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=true
Starting container container-1743307567
Hello from container
Container container-1743307567 exited@j143 ➜ /workspaces/basic-docker-engine (main) $ sudo ./basic-docker run /bin/busybox echo "Hello from BusyBox"
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=false
Starting container container-1744512443
Hello from BusyBox
Container container-1744512443 exited@j143 ➜ /workspaces/basic-docker-engine (main) $ chmod +x verify.sh
@j143 ➜ /workspaces/basic-docker-engine (main) $ ./verify.sh
==== System Information ====
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=false
Lean Docker Engine - System Information
=======================================
Go version: go1.24.1
OS/Arch: linux/amd64
Running in container: true
Namespace privileges: true
Cgroup access: false
Available features:
- Process isolation: true
- Network isolation: true
- Resource limits: false
- Filesystem isolation: true
===========================
==== Running Simple Command ====
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=true
Starting container container-1743307590
Hello from container
Container container-1743307590 exited
==== Listing Containers ====
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=true
CONTAINER ID STATUS COMMAND
container-1743307284 N/A N/A
container-1743307290 N/A N/A
container-1743307567 N/A N/A
container-1743307590 N/A N/A
==== Testing with busybox ====
Environment detected: inContainer=true, hasNamespacePrivileges=true, hasCgroupAccess=true
Starting container container-1743307590
Error: failed to create symlink for sh: symlink busybox /tmp/basic-docker/containers/container-1743307590/rootfs/bin/sh: file exists
==== Skipping isolation tests (needs root) ====
==== All tests completed ====
graph TD
A[Unit Tests] --> B[Integration Tests]
B --> C[End-to-End Tests]
C --> D[Verification Script]
%% Styling
classDef process fill:#ffe0d0,stroke:#ff8030,stroke-width:2px
class A,B,C,D process
- Unit Tests: Present in
main_test.goandimage_test.go.- Includes tests for
AddResourceCapsule,CapsuleManager, and Docker integration. - Benchmarks for capsule and volume access.
- Includes tests for
- Integration Tests: Covered partially in
verify.sh.- Verifies container creation, image listing, and network functionality.
- End-to-End Tests: Basic functionality tested via
verify.sh.- Simulates real-world usage scenarios.
- Verification Script:
verify.shruns additional checks and validations.- Includes system information, container commands, and BusyBox tests.