Cloud Native 31 min read

Implementing a Simple Docker with Shell: Namespaces, Cgroups, and OverlayFS

The article walks readers through building a minimal Docker‑like container runtime entirely in shell, explaining and demoing Linux namespaces, cgroups, and OverlayFS for isolation, resource control, and layered filesystems, and culminates in a concise Bocker script that implements core Docker commands.

vivo Internet Technology
vivo Internet Technology
vivo Internet Technology
Implementing a Simple Docker with Shell: Namespaces, Cgroups, and OverlayFS

This article, authored by the Vivo Internet Operations team, demonstrates how to build a minimal Docker‑like container runtime using only shell commands. It explains the core Linux kernel features required for container isolation—Cgroup, Namespace, and RootFS—and shows how to combine them interactively to understand Docker's underlying mechanisms.

1. Purpose

The goal is to deepen understanding of container technology by recreating a stripped‑down Docker implementation with shell scripts, focusing on the isolation capabilities provided by namespaces, resource control via cgroups, and filesystem layering with overlayfs.

2. Technical Breakdown

2.1 Namespace

Linux namespaces provide kernel‑level isolation for UTS, IPC, mount, PID, network, and user resources. They allow processes in different namespaces to have independent views of global system resources.

Supported namespace types are illustrated in the original article (UTS, IPC, mount, PID, network, user).

2.1.1 System Calls

clone()
setns()
unshare()

2.1.2 Viewing Process Namespaces

# 查看当前 bash 进程关联的 Namespace
ls -l /proc/$$/ns

The output shows symbolic links such as ipc -> ipc:[4026531839] , where the inode number uniquely identifies a namespace instance.

2.1.3 Example Commands

# nsenter: 加入指定进程的指定类型的 namespace 中,然后执行参数中指定的命令。
# unshare: 离开当前指定类型的 namespace, 创建且加入新的 namespace。
# ipcmk / ipcs: 操作 System V IPC 对象。

2.1.4 IPC Namespace Demo

The article walks through two shells (A and B) that create and join an IPC namespace, set hostnames, and manipulate message queues to illustrate isolation.

# 在 shell A 中查看当前 namespace
readlink /proc/$$/ns/uts /proc/$$/ns/ipc
# 创建并加入新的 namespace
nsenter -t 30372 -u -i /bin/bash

After switching to shell B, the hostname changes to shell‑B , confirming the namespace switch.

2.1.5 Net Namespace Demo

# 创建两个 netns r1 和 r2
ip netns add r1
ip netns add r2
# 将 veth 对等接口加入对应的 netns
ip link set veth0_11 netns r1
ip link set veth1_11 netns r2
# 在 r1 中配置 IP 并 ping r2
ip addr add 172.18.0.11/24 dev veth0_11
ip link set veth0_11 up
ping 172.18.0.12

The successful ping demonstrates network isolation between the two namespaces.

2.2 Cgroup

Cgroups group processes for resource limiting, prioritization, accounting, and control. The article lists the four main components: task, cgroup, subsystem, and hierarchy.

Example commands to inspect cgroup support:

# 查看系统支持的 subsystem
cat /proc/cgroups
# 查看当前进程所属的 cgroup
cat /proc/$$/cgroup

Creating and configuring cgroups:

# 创建 cgroup 并限制 CPU 与内存
cgcreate -g cpu,cpuacct,memory:/mygroup
cgset -r cpu.shares=512 mygroup
cgset -r memory.limit_in_bytes=$((512*1000000)) mygroup

2.3 Rootfs and OverlayFS

Rootfs is the filesystem visible inside a container. Docker uses a read‑only layer (lower) and a writable layer (upper) combined via overlayfs (merged). The article explains the three directories used by overlayfs: lower, upper, and work.

OverlayFS demo commands:

# 创建目录结构
mkdir upper lower merged work
# 在 lower 和 upper 中放置文件
echo "lower" > lower/in_lower.txt
echo "upper" > upper/in_upper.txt
echo "lower" > lower/in_both.txt
echo "upper" > upper/in_both.txt
# 挂载 overlayfs
mount -t overlay overlay -o lowerdir=lower,upperdir=upper,workdir=work merged
# 查看合并后的文件视图
cat merged/in_both.txt   # 输出 "upper"
# 在 merged 中创建新文件,实际写入 upper
touch merged/new_file
# 删除在 both 中的文件,生成 whiteout
rm -f merged/in_both.txt

The demo shows how reads prioritize the upper layer and writes always go to the upper layer, while deletions create whiteout files.

3. Bocker – A Minimal Docker Implementation

The script (≈130 lines) implements Docker‑like commands: pull , init , images , ps , run , exec , logs , commit , and rm . It leverages the previously described namespaces, cgroups, and overlayfs to create isolated containers.

#!/usr/bin/env bash
set -o errexit -o nounset -o pipefail
# ... (full script omitted for brevity) ...
case $1 in
    pull|init|rm|images|ps|run|exec|logs|commit) bocker_$1 "${@:2}" ;;
    *) bocker_help "$0" ;;
esac

The README lists prerequisites (overlayfs, iproute2, iptables, libcgroup‑tools, util‑linux ≥2.25.2, coreutils ≥7.5) and required host configuration (bridge br1 with 172.18.0.1/24, IP forwarding, NAT rules).

Implemented features include Docker‑style build, pull, image listing, container listing, run, exec, logs, commit, removal, networking, and cgroup quota support.

4. Conclusion

The article emphasizes that the educational value lies in constructing a functional, lightweight container runtime with shell scripts, which helps readers grasp Docker’s core technologies and provides practical insight for troubleshooting container‑related issues.

DockercontainerizationcgroupsBockerLinux namespacesOverlayFSshell scripting
vivo Internet Technology
Written by

vivo Internet Technology

Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.