World map

 

BM: Baca dalam Bahasa Melayu

World D6: Under the Hood · Boss challenge

X-ray

You will learn: to turn a plain process into a container, one namespace and one limit at a time.

Checked with Docker Engine 29 on 31 Oct 2026

The problem

Boss mission: the X-ray. node server.js is a plain process on Aina’s laptop. You will make it a container, one switch at a time. First: what is a container, really?

Pick one answer.

Try it

Room 1: hide the laptop’s other processes from it.

Turn on the switch that hides other processes.

What it can see (namespaces)

  • Processes it sees

    • 1 /sbin/init
    • 412 sshd
    • 655 containerd
    • 701 dockerd
    • 1880 firefox
    • 4242 node server.js← this process
  • Files it sees

    • /home/aina/kedai/server.js
    • /home/aina/.ssh/id_ed25519
    • /home/aina/Photos/
    • /var/lib/docker/

Predict

PID is on. Yet ps inside would still list the laptop’s processes. Why?

Pick one answer.

Try it

Room 2: turn on Docker’s own set of blinkers, until the banner says container.

Turn on the switches docker run uses, until it is a container.

Just a process. It sees the whole laptop.

What it can see (namespaces)

  • Processes it sees

    • 1 node server.js← this process

    Inside, it is PID 1. But ps reads /proc. Docker also mounts a fresh /proc (the Mount switch).

  • Files it sees

    • /home/aina/kedai/server.js
    • /home/aina/.ssh/id_ed25519
    • /home/aina/Photos/
    • /var/lib/docker/
  • Network

    • lo 127.0.0.1
    • wlan0 192.168.1.20
    • docker0 172.17.0.1
  • Hostname

    aina-laptop
  • Shared memory

    • shared memory from firefox
    • shared memory from pulseaudio
  • User

    Inside: uid=0(root)

    On the laptop: uid=0 (root on the laptop too!)

    Docker uses this switch only in rootless mode, or with userns-remap.

Try it

Room 3: now a real one. web runs nginx. See it from inside with docker exec web ps, then from the laptop with docker top web.

Your laptop~

  • Laptop port 8080 → web port 80

Lunchboxes (containers)

  • webrunning
    from nginx:1.30-alpine 8080→80

Frozen packs (images)

  • nginx:1.30-alpine8 layers · 93.5MB · in use

1 containers (1 running), 1 images, 0 lockers.

Try it

Room 4: add portion limits, and the last blinker. Turn on every switch.

Turn on every switch. Watch what the process can see and use.

A container now: Docker's default switches are on.

What it can see (namespaces)

  • Processes it sees

    • 1 node server.js← this process
  • Files it sees

    • /app/server.js
    • /usr/local/bin/node
    • /etc/alpine-release

    Docker also swaps the root folder for the image's files.

  • Network

    • lo 127.0.0.1
    • eth0 172.17.0.2

    Docker plugs in a virtual cable, called eth0.

  • Hostname

    3f9c2a7b1d04
  • Shared memory

    Nothing shared. Other apps' memory is hidden.

  • User

    Inside: uid=0(root)

    On the laptop: uid=0 (root on the laptop too!)

    Docker uses this switch only in rootless mode, or with userns-remap.

What it can use (cgroups)

  • Limits

    Memory
    No limit: all 16 GB
    CPU
    No limit: all 8 CPUs
    Processes
    No limit

Check

Last room: what happens when you type docker run? Put it in order, first at the top.

First step at the top. Put these in order. Use the arrows, or drag.

  • containerd stacks the image layers with a fresh top sheet
  • You type docker run
  • dockerd passes the order to containerd
  • Your app starts as PID 1, and runc leaves
  • runc switches on namespaces and cgroups

You did it!

You can now build a container in your head, switch by switch.

Go deeper (optional)

Real rep (optional, Linux): flip real switches with unshare. A new network namespace has only lo, and it starts down. Nothing changes on your laptop.

Real mission

  1. sudo unshare --pid --fork --mount-proc --uts --net sh
  2. ps
  3. ip link
  4. exit

0 of 4 steps done · Your ticks are saved.