Skip to content

Docker Internals Deep Dive

🎯 Mục tiêu

🎯 Sau bài thực hành này, bạn sẽ:

  • Hiểu và thực hành Linux namespaces bằng unshare
  • Khám phá cgroups để giới hạn tài nguyên container
  • Phân tích cấu trúc overlay filesystem layers
  • Trace container runtime để hiểu vòng đời container

Mô tả bài tập

Container không phải máy ảo — chỉ là process Linux cô lập bằng namespaces và giới hạn bằng cgroups. Bài tập này giúp bạn "mổ xẻ" Docker.

WARNING

Yêu cầu Linux host với quyền root. Trên macOS/Windows, dùng docker run --privileged -it ubuntu bash.

Yêu cầu

Bài 1: Namespaces với unshare

bash
ls -la /proc/$$/ns/
sudo unshare --pid --fork --mount-proc bash
ps aux  # Chỉ thấy bash và ps — hoàn toàn cô lập!
exit

Yêu cầu: Tạo namespace với --net và chứng minh namespace mới không thấy network interfaces của host.

Bài 2: Inspect Cgroups

bash
docker run -d --name cgroup-test --memory=128m nginx:alpine
CONTAINER_ID=$(docker inspect --format '{{.Id}}' cgroup-test)
cat /sys/fs/cgroup/docker/$CONTAINER_ID/memory.max
cat /sys/fs/cgroup/docker/$CONTAINER_ID/memory.current

Yêu cầu: Chạy stress test trong container, quan sát memory.current thay đổi. Thử vượt limit và giải thích OOM behavior.

Bài 3: Overlay Filesystem Layers

bash
docker inspect --format '{{json .GraphDriver.Data}}' nginx:alpine | python3 -m json.tool
UPPER=$(docker inspect --format '{{.GraphDriver.Data.UpperDir}}' <container_id>)
ls $UPPER  # Chỉ chứa file container đã thay đổi

Yêu cầu: Chạy Nginx container, tạo file mới bên trong, xác nhận file chỉ xuất hiện ở UpperDir.

Bài 4: Trace Container Runtime

Theo dõi Docker tạo container như thế nào.

bash
docker events --filter type=container &
docker run --rm -d --name traced nginx:alpine
# Quan sát events: create → start → ...

PID=$(docker inspect --format '{{.State.Pid}}' traced)
ls -la /proc/$PID/ns/    # Namespaces của container
ls -la /proc/1/ns/        # So sánh với host

Yêu cầu: So sánh namespaces giữa container process và PID 1 host. Giải thích namespace nào khác nhau.

Gợi ý

Gợi ý Bài 1

unshare --net bash tạo network namespace trống. Dùng ip link — chỉ thấy loopback lo.

Gợi ý Bài 2

Cgroups v2: /sys/fs/cgroup/system.slice/docker-<id>.scope/. Cgroups v1: /sys/fs/cgroup/memory/docker/<id>/.

Gợi ý Bài 3

OverlayFS: LowerDir (read-only layers), UpperDir (container writes), MergedDir (union view).

Lời giải tham khảo

Xem lời giải
bash
# Bài 1: Network namespace isolation
sudo unshare --net bash
ip link  # Chỉ thấy lo (loopback)
exit

# Bài 2: Cgroups memory monitoring
docker run -d --name stress-test --memory=128m ubuntu:22.04 sleep 3600
docker exec stress-test apt-get update && apt-get install -y stress
docker exec stress-test stress --vm 1 --vm-bytes 100M --timeout 10s

# Bài 3: Overlay filesystem inspection
docker run -d --name overlay-test nginx:alpine
docker exec overlay-test touch /tmp/newfile.txt
UPPER=$(docker inspect --format '{{.GraphDriver.Data.UpperDir}}' overlay-test)
ls -la $UPPER/tmp/  # newfile.txt chỉ tồn tại ở UpperDir