๐ I'm Building My Own Container Runtime!
This is part of a complete series where I'm building Conti - a container runtime from scratch. Check it out on GitHub!
About This Series:
- I'm sharing everything I learn while building my own container runtime
- Most concepts come from videos, documentation, and LLM-assisted learning (for educational purposes)
- Focus: Understanding through practice - raw Linux commands and practical implementation
- Important: When building your own container, DON'T copy code from sources - it kills the fun! Write it yourself, break things, debug, and learn.
Why Build Your Own?
- Deep understanding of how containers really work
- Master low-level Linux concepts
- Learn by doing, not just reading
- It's incredibly fun when things finally click!
How modern containers achieve incredible efficiency and isolation
๐ฌ Act 1: The Party Problem
Imagine you're organizing a massive tech conference with three separate tracks happening simultaneously:
๐จ The Design Track - UI/UX designers discussing Figma and Sketch
๐ป The DevOps Track - Engineers exploring Kubernetes and CI/CD
๐ค The AI Track - Researchers presenting machine learning models
Each track needs:
- A presentation room (isolated space)
- Audio/visual equipment (shared resources)
- Custom materials (track-specific content)
- Whiteboards for notes (temporary changes)
The Expensive Approach โ
You could buy three complete sets of everything:
- 3 projectors @ $2,000 each = $6,000
- 3 sound systems @ $1,500 each = $4,500
- 3 furniture sets @ $3,000 each = $9,000
Total: $19,500 ๐ฑ
The Smart Approach โ
What if you could:
- Share the expensive equipment (projectors, furniture)
- Give each track private notebooks for their own notes
- Let them customize only what they need
Total: $6,500 + 3 notebooks
This is exactly what overlay filesystems do for containers!
๐๏ธ Act 2: Understanding the Architecture
The Three-Layer Cake ๐
Think of the overlay filesystem as a delicious three-layer cake:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐ฐ MERGED LAYER (What You See) โ โ The complete cake you eat
โ Combines everything below โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ๏ธ UPPER LAYER (Your Changes) โ โ Your frosting and decorations
โ Read/Write - Personal Edits โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ ๐ฆ LOWER LAYER (Base Recipe) โ โ The original cake (untouched)
โ Read-Only - Shared Foundation โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ฏ The Lower Layer (The Foundation)
- Read-only - Like a published cookbook
- Contains your base operating system (Ubuntu, Alpine Linux)
- Shared across ALL containers
- Never gets modified
โ๏ธ The Upper Layer (Your Workspace)
- Read/write - Your personal notepad
- Stores all YOUR changes
- Unique to each container
- Where creativity happens!
๐ The Merged Layer (The Magic View)
- What users actually see and interact with
- Automatically combines Lower + Upper
- Feels like one complete filesystem
๐ช Act 3: The Copy-on-Write Magic Show
Let me show you the most clever trick in the container world: Copy-on-Write (COW)
Scenario: The Recipe Book ๐
Imagine you have a master recipe book (lower layer) with 100 recipes.
Day 1: You read "Chocolate Cake" โ No copying needed!
You're just reading from the shared book. Fast and efficient!
Day 2: You want to modify "Chocolate Cake" โ NOW the magic happens!
STEP 1: System spots you editing
โ
STEP 2: "Hold on! Let me copy this page to YOUR notebook!"
โ
STEP 3: Copy "Chocolate Cake" to upper layer
โ
STEP 4: You modify YOUR copy
โ
STEP 5: Original recipe stays pristine โจ
The Result:
- Master book: Still has original "Chocolate Cake" โ
- Your notebook: Has your modified "Spicy Chocolate Cake" โ
- Everyone else: Still sees the original recipe โ
Real Container Example
# Container starts with nginx.conf from base image
$ cat /etc/nginx/nginx.conf
โ Reading from LOWER layer (shared base image)
# You edit the config file
$ echo "worker_processes 4;" >> /etc/nginx/nginx.conf
โ System COPIES file to UPPER layer
โ Your edit goes into YOUR copy
โ Base image remains unchanged!
# Your change is private to YOUR container
โ 1000 other nginx containers still see the original
๐ฏ Act 4: The Real-World Impact
Before Overlay FS: The Dark Ages ๐ฑ
Launching 100 web applications:
App 1: Ubuntu (500MB) + Node.js (100MB) = 600MB
App 2: Ubuntu (500MB) + Node.js (100MB) = 600MB
App 3: Ubuntu (500MB) + Node.js (100MB) = 600MB
...
App 100: Ubuntu (500MB) + Node.js (100MB) = 600MB
TOTAL: 60,000 MB (60 GB!) ๐
After Overlay FS: The Renaissance โจ
Shared Ubuntu: 500MB (one time!)
Shared Node.js: 100MB (one time!)
App 1 changes: 2MB
App 2 changes: 3MB
App 3 changes: 1MB
...
App 100 changes: 2MB
TOTAL: 600MB + 200MB changes = 800MB ๐
SAVED: 59.2 GB (98.7% reduction!)
๐ ๏ธ Act 5: Hands-On Workshop
Let's build our own overlay filesystem step-by-step!
Workshop Setup: Three Coffee Shops โ
You're running three coffee shops, each needs menus and custom recipes.
Step 1: Create the Directory Structure
# Our shared base (the franchise template)
mkdir -p coffee-franchise/{base,shop-downtown,shop-uptown,shop-campus}
mkdir -p coffee-franchise/work-{downtown,uptown,campus}
mkdir -p coffee-franchise/merged-{downtown,uptown,campus}
cd coffee-franchise
# Create shared base menu (lower layer)
echo "1. Espresso - $3" > base/menu.txt
echo "2. Latte - $4" >> base/menu.txt
echo "3. Cappuccino - $4.50" >> base/menu.txt
echo "Standard Coffee Brewing Guide" > base/brewing.txt
Step 2: Mount Downtown Shop (First Container)
# Create the overlay filesystem
sudo mount -t overlay overlay \
-o lowerdir=base,upperdir=shop-downtown,workdir=work-downtown \
merged-downtown
# Check what's visible
ls merged-downtown/
# Output: menu.txt brewing.txt (from base!)
Step 3: Make Shop-Specific Changes
# Downtown caters to business people - add premium options
echo "4. Cold Brew - $5" >> merged-downtown/menu.txt
echo "Downtown Specialty: Extra Strong!" > merged-downtown/special.txt
# Check what happened:
ls base/
# Output: menu.txt brewing.txt (unchanged!)
ls shop-downtown/
# Output: menu.txt special.txt (YOUR changes only!)
Step 4: Create Another Shop (Second Container)
# Mount campus shop
sudo mount -t overlay overlay \
-o lowerdir=base,upperdir=shop-uptown,workdir=work-uptown \
merged-uptown
# Campus caters to students - add budget options
echo "4. Small Coffee - $2" >> merged-uptown/menu.txt
echo "Campus Special: Student Discount 20%!" > merged-uptown/special.txt
# Each shop sees different menus!
cat merged-downtown/special.txt
# Output: Downtown Specialty: Extra Strong!
cat merged-uptown/special.txt
# Output: Campus Special: Student Discount 20%!
๐ What We Achieved:
โ
One base menu shared across all shops
โ
Custom modifications per shop
โ
Complete isolation - changes don't affect others
โ
Massive space savings - one copy of common files
๐ญ Act 6: The Delete Mystery
What happens when you delete a file from the lower layer?
# Try to delete the base menu from downtown
rm merged-downtown/menu.txt
# The file disappears from downtown view... but wait!
ls merged-downtown/
# Output: brewing.txt special.txt (menu.txt is gone!)
# Check the other shop
ls merged-uptown/
# Output: menu.txt brewing.txt special.txt (still there!)
# The secret: a WHITEOUT file
ls -la shop-downtown/
# Output: c--------- 1 root root 0, 0 menu.txt (special marker!)
The Magic:
Instead of deleting from base (impossible - it's read-only!), the system creates a special "whiteout" marker that hides the file only in your view.
๐ Act 7: Real Container Architecture
Here's how Docker/Kubernetes actually use this:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ YOUR RUNNING CONTAINER (Merged) โ
โ What you see when you 'docker exec' โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ CONTAINER LAYER (Upper) โ๏ธ โ
โ - Your app logs โ
โ - Temp files โ
โ - Runtime changes โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ APP LAYER (Lower 3) ๐ฑ โ
โ - Your application code โ
โ - App dependencies โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ RUNTIME LAYER (Lower 2) โ๏ธ โ
โ - Python/Node.js/Java โ
โ - Libraries โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ BASE OS LAYER (Lower 1) ๐๏ธ โ
โ - Ubuntu/Alpine Linux โ
โ - Core utilities โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโ All "Lower" layers are SHARED!
The Dockerfile Connection
FROM ubuntu:20.04 # โ Lower Layer 1 (shared!)
RUN apt-get install python3 # โ Lower Layer 2 (shared!)
COPY app.py /app/ # โ Lower Layer 3 (shared!)
CMD ["python3", "app.py"] # โ Upper Layer (YOUR changes!)
Each line creates a layer. When you run 1000 containers from this image:
- Ubuntu layer: Stored ONCE
- Python layer: Stored ONCE
- App layer: Stored ONCE
- Runtime changes: 1000 unique upper layers (small!)
Top comments (0)