How It Works #

Docker sering dipersepsikan sebagai “alat ajaib yang menjalankan container”. Tapi tidak ada sihir di dalamnya. Apa yang Docker lakukan adalah mengeksploitasi fitur-fitur kernel Linux yang sudah ada sejak lama — namespaces, cgroups, union filesystem, capability, dan security modules — lalu membungkusnya dengan API yang developer-friendly. Container yang kamu jalankan dengan satu perintah docker run sebenarnya adalah proses Linux biasa yang diberi view dan batas tertentu oleh kernel.

Artikel ini adalah yang paling teknikal di section Architecture. Kita akan membedah apa yang sebenarnya terjadi di bawah kap saat kamu menjalankan docker run nginx — dari CLI mengirim request, daemon memproses, runtime menyiapkan namespace dan cgroup, sampai proses nginx benar-benar hidup dan terlihat sebagai satu-satunya proses di “sistem”-nya sendiri. Setelah membaca artikel ini, kamu tidak akan pernah lagi melihat Docker sebagai kotak hitam.

Container di Level Kernel — Bukan Virtual Machine #

Langkah pertama yang paling penting untuk dipahami: container bukan virtual machine. Tidak ada hypervisor, tidak ada emulasi hardware, tidak ada boot sequence. Yang ada adalah proses biasa di host, dengan batas-batas virtual yang diterapkan oleh kernel.

flowchart TB
    subgraph USERSPACE["User Space"]
        CLI[docker CLI]
        DAEMON[dockerd]
        CONTAINERD[containerd]
        RUNC[runc]
    end

    subgraph KERNEL["Linux Kernel"]
        NS["Namespaces<br/>(isolasi view)"]
        CG["cgroups<br/>(isolasi resource)"]
        UFS["Union Filesystem<br/>(OverlayFS)"]
        NET["Network stack<br/>(bridge, veth, iptables)"]
        SEC["Security modules<br/>(seccomp, capabilities)"]
    end

    subgraph HW["Hardware"]
        CPU[CPU]
        RAM[RAM]
        DISK[Disk]
        NIC[Network]
    end

    CLI --> DAEMON --> CONTAINERD --> RUNC
    RUNC --> NS
    RUNC --> CG
    RUNC --> UFS
    RUNC --> NET
    RUNC --> SEC
    NS --> HW
    CG --> HW
    UFS --> DISK
    NET --> NIC
    SEC --> CPU

Tiga fitur kernel utama yang menjadi pondasi container:

  1. Namespaces — membuat proses merasa “punya sistem sendiri”.
  2. cgroups — membatasi dan mengukur resource yang boleh dipakai proses.
  3. Union filesystem — menggabungkan banyak layer jadi satu mount point.

Ditambah fitur pendukung:

  • Capabilities — membatasi privilege root (potong kemampuan, jangan matikan root sepenuhnya).
  • Seccomp — filter system call yang boleh dipanggil.
  • AppArmor / SELinux — mandatory access control (MAC).

Detail menarik: semua fitur ini sudah ada di Linux jauh sebelum Docker. chroot (1982) adalah cikal bakal union filesystem. Namespaces pertama (mount) muncul di 2002. cgroups muncul di 2007. Docker (2013) bukan penemu teknologi container; Docker adalah pembungkus yang membuat teknologi ini mudah dipakai oleh jutaan developer.


Namespaces — Ilusi Isolasi #

Namespace adalah fitur kernel Linux yang membuat sekumpulan proses melihat resource sistem secara berbeda dari proses lain. Ada tujuh namespace yang dipakai container modern.

Tujuh Namespace Docker #

Namespace Mengisolasi File di /proc Efek Visual
PID Process ID /proc/<pid>/ns/pid Container melihat PID sendiri mulai dari 1
NET Network interface, port, routing /proc/<pid>/ns/net Container punya NIC virtual sendiri
MNT Filesystem mount points /proc/<pid>/ns/mnt Container lihat / yang berbeda
UTS Hostname dan NIS domain /proc/<pid>/ns/uts Container bisa punya hostname sendiri
IPC Inter-process communication /proc/<pid>/ns/ipc Container tak bisa kirim signal ke host
USER User dan group ID /proc/<pid>/ns/user UID 0 di container = UID 100000 di host
CGROUP View cgroup hierarchy /proc/<pid>/ns/cgroup Container hanya lihat cgroup sendiri

Namespace dalam Aksi #

Untuk melihat namespace bekerja, kamu bisa membuat namespace manual tanpa Docker sama sekali. Linux menyediakan tool unshare untuk ini:

# Buat PID namespace baru dan jalankan shell di dalamnya
sudo unshare --pid --fork /bin/bash

# Di dalam namespace baru, PID 1 adalah shell ini
ps aux
# Output: PID 1 adalah /bin/bash
# Tidak ada proses host yang terlihat

# Sekarang keluar
exit
# Kembali ke namespace host
ps aux
# Semua proses host terlihat lagi

Perintah unshare melakukan hal yang sama dengan yang dilakukan runc saat membuat container: clone process dengan flag namespace baru, lalu exec program di namespace itu. Docker Container pada dasarnya adalah unshare yang dibungkus dengan konfigurasi declarative.

Namespace Bersifat Hierarkis #

Namespace bisa di-nested: namespace di dalam namespace. Ini yang memungkinkan rootless Docker bekerja — daemon berjalan di user namespace, container di dalam namespace lain.

flowchart TB
    HOST["Host PID 1<br/>(init)"]
    DAEMON["dockerd<br/>(Host PID 1234)"]
    C1A["Container A<br/>PID 1 di namespace-nya"]
    C1B["Container B<br/>PID 1 di namespace-nya"]

    HOST --> DAEMON
    DAEMON --> C1A
    DAEMON --> C1B

Dari sisi host, daemon dockerd punya PID biasa (misal 1234). Dari sisi container, PID 1234 di map ke PID berbeda (atau tidak terlihat sama sekali jika --pid=host tidak diaktifkan). Container A dan B punya PID 1 yang berbeda di namespace-nya masing-masing, tapi di host mereka adalah PID biasa yang berbeda juga.

Jebakan umum: mengira namespace memberikan keamanan penuh. Namespace memberikan isolasi view, bukan isolasi kernel. Jika ada bug di kernel yang memungkinkan proses escape dari namespace, attacker bisa mengakses resource host. Itulah kenapa Docker menambahkan lapisan keamanan tambahan (seccomp, AppArmor, capability dropping) di atas namespace.

cgroups — Pembatasan Resource #

cgroups (control groups) adalah fitur kernel yang membatasi, mengukur, dan mengisolasi resource usage dari sekumpulan proses. Ini adalah pasangan namespace: kalau namespace mengisolasi apa yang dilihat, cgroup mengisolasi berapa banyak yang boleh dipakai.

Controller cgroups #

Setiap “resource” yang bisa dibatasi punya controller masing-masing. Di cgroups v1, tiap controller di-mount terpisah; di v2, mereka unified.

Resource cgroup v1 cgroup v2 Contoh Flag Docker
CPU cpu, cpuacct cpu (unified) --cpus=1.5
Memory memory memory --memory=512m
Block I/O blkio io --device-read-bps
Network net_cls, net_prio net_cls (via tc) (tidak ada flag langsung)
PIDs pids pids --pids-limit=100
Devices devices devices --device (whitelist)
Freezer freezer freezer (untuk docker pause)

Cara Kerja cgroups #

Setiap proses Linux terdaftar di cgroup hierarchy. cgroup hierarchy adalah struktur tree-like di filesystem (/sys/fs/cgroup/), di mana setiap node adalah cgroup dan setiap proses menjadi anggota salah satu node.

flowchart TB
    ROOT["/sys/fs/cgroup/"]
    DOCKER["docker/"]
    CONTAINER_A["docker/abc123.../"]
    CONTAINER_B["docker/def456.../"]
    KUBE["kubepods/"]
    POD_A["kubepods/pod-xxx/"]
    POD_B["kubepods/pod-yyy/"]

    ROOT --> DOCKER
    ROOT --> KUBE
    DOCKER --> CONTAINER_A
    DOCKER --> CONTAINER_B
    KUBE --> POD_A
    KUBE --> POD_B

Saat Docker membuat container, ia:

  1. Membuat direktori baru di /sys/fs/cgroup/<controller>/docker/<container-id>/.
  2. Menulis nilai limit ke file konfigurasi (memory.max, cpu.max, dll).
  3. Menulis PID container ke file cgroup.procs atau tasks (bergantung versi).

Kernel kemudian enforces limit yang sudah ditulis: setiap kali proses mencoba mengalokasi memory atau CPU, kernel cek dulu ke cgroup yang relevan, dan tolak jika limit terlampaui.

Contoh Konkret Memory Limit #

# Buat container dengan memory limit 256 MB
docker run -d --memory=256m --name test nginx

# Cek cgroup container
CONTAINER_PID=$(docker inspect test --format '{{.State.Pid}}')
cat /sys/fs/cgroup/memory/docker/$(docker inspect test --format '{{.Id}}')/memory.limit_in_bytes
# Output: 268435456 (= 256 * 1024 * 1024)

# Cek OOM kill count
cat /sys/fs/cgroup/memory/docker/.../memory.failcnt
# Akan naik jika container pernah kena OOM

Saat container mencoba alokasi memory yang melebihi limit, kernel mengirim SIGKILL ke proses (Out-Of-Memory kill). Tidak ada graceful handling di level container — aplikasi yang ditulis dengan buruk bisa crash tiba-tiba.

Best practice: selalu set --memory dan --cpus di production. Tanpa limit, satu container yang punya memory leak bisa menghabiskan semua RAM host dan membuat container lain di-OOM-kan. Di Kubernetes, ini berlaku juga — set resources.limits untuk semua pod.

Union Filesystem — Layered Storage #

Union filesystem (OverlayFS di Linux) adalah teknologi yang membuat Docker image bisa kecil dan image layer bisa di-share. Ini adalah salah satu fitur yang paling sering tidak dihargai orang tapi paling berdampak di operasional.

Anatomi OverlayFS #

OverlayFS bekerja dengan menggabungkan dua direktori menjadi satu mount point:

  • Lowerdir — read-only layer (image layer).
  • Upperdir — read-write layer (container layer).
  • Workdir — internal, untuk atomic operations.
  • Merged — view yang dilihat user (gabungan lower + upper).
flowchart TB
    subgraph LOWER["Lowerdir (image, read-only)"]
        L1["Layer 4: app code (10 MB)"]
        L2["Layer 3: dependencies (50 MB)"]
        L3["Layer 2: apt packages (200 MB)"]
        L4["Layer 1: base image (77 MB)"]
    end

    subgraph UPPER["Upperdir (container, read-write)"]
        U1["Container layer (5 MB initially)"]
    end

    subgraph MERGED["Merged view /"]
        M1["/ (terlihat sebagai satu filesystem utuh)"]
    end

    LOWER --> MERGED
    UPPER --> MERGED

Copy-on-Write #

OverlayFS menggunakan copy-on-write (CoW): saat container ingin memodifikasi file dari lowerdir, file itu pertama di-copy ke upperdir, baru dimodifikasi. File asli di lowerdir tetap tidak berubah.

sequenceDiagram
    participant App as App di Container
    participant U as Upperdir
    participant L as Lowerdir
    participant FS as Filesystem view

    App->>FS: read /etc/nginx/nginx.conf
    FS->>L: read dari lowerdir (cache hit)
    L-->>FS: file content
    FS-->>App: data

    App->>FS: write /etc/nginx/nginx.conf
    FS->>U: copy file ke upperdir
    U-->>FS: file copied
    FS->>U: write ke upperdir
    U-->>App: success

    Note over L: file asli tetap utuh
    Note over U: file baru di upperdir

CoW ini yang membuat container start cepat: tidak ada “disk initialization” — semua layer image sudah ada, container hanya perlu setup upperdir kosong dan mount semuanya.

Dampak Operasional #

Aspek Dampak
Storage Upperdir biasanya kecil (5–50 MB) karena perubahan runtime minim
Pull time Layer image yang sama dipakai banyak container → tidak diulang
Build time Layer yang tidak berubah dipakai cache → build inkremental
Backup Backup hanya upperdir untuk snapshot container state
Performance CoW ada overhead untuk write pertama ke file besar, tapi minimal untuk read

Driver storage lain yang dipakai Docker:

  • overlay2 — default di Linux modern, paling umum.
  • btrfs — copy-on-write filesystem, juga support layer.
  • zfs — kombinasi volume manager + filesystem, populer di FreeBSD/illumos.
  • devicemapper — block-level, legacy, tidak direkomendasikan.

Cara cek storage driver: docker info | grep "Storage Driver". Jika masih devicemapper, pertimbangkan migrasi ke overlay2 (lebih cepat, lebih hemat space, support lebih baik di kernel modern).


Container Networking — Bagaimana Container Mendapat IP #

Setiap container yang berjalan punya network interface virtual di namespace network sendiri. Bagaimana interface ini dibuat dan disambungkan ke host adalah topik yang sering bikin bingung pemula.

Komponen Networking Container #

flowchart LR
    subgraph HOST["Host Network Namespace"]
        DOCKER0["docker0 bridge<br/>172.17.0.1/16"]
        ETH0["eth0 (host network)"]
        IPTABLES["iptables rules"]
    end

    subgraph NS1["Container A Network Namespace"]
        ETH_A["eth0<br/>172.17.0.2/16"]
    end

    subgraph NS2["Container B Network Namespace"]
        ETH_B["eth0<br/>172.17.0.3/16"]
    end

    VETH_A["vethXXX (host side)"]
    VETH_B["vethYYY (host side)"]

    ETH_A --- VETH_A
    ETH_B --- VETH_B
    VETH_A --- DOCKER0
    VETH_B --- DOCKER0
    DOCKER0 --- ETH0
    DOCKER0 --- IPTABLES

Lima komponen utama dalam networking container default bridge:

  1. Network namespace — tiap container punya namespace sendiri untuk network.
  2. veth pair — virtual ethernet cable yang menghubungkan dua namespace. Satu ujung di container, satu ujung di host.
  3. Bridge (docker0) — virtual switch di host yang menyambungkan semua veth pair dari container.
  4. NAT (iptables) — rules yang menerjemahkan traffic dari container ke internet (masquerade).
  5. Port mapping (DNAT) — rules yang meneruskan traffic dari port host ke port container.

Alur Koneksi Container ke Internet #

sequenceDiagram
    participant C as Container (172.17.0.2)
    participant V as veth pair
    participant B as docker0 bridge
    participant I as iptables
    participant H as Host eth0
    participant W as Web (1.1.1.1)

    C->>V: HTTP GET 1.1.1.1 (source: 172.17.0.2)
    V->>B: forward ke bridge
    B->>I: trigger NAT (POSTROUTING)
    I->>I: rewrite source IP ke host IP (masquerade)
    I->>H: forward
    H->>W: HTTP request
    W-->>H: HTTP response
    H-->>I: response masuk
    I-->>I: reverse NAT
    I-->>V: forward ke bridge
    V-->>C: HTTP response (dest: 172.17.0.2)

Port Mapping — Membuat Container Bisa Diakses dari Luar #

# Publish port 8080 host ke 80 container
docker run -d -p 8080:80 nginx

Yang terjadi di belakang layar:

# Docker menambahkan iptables rule:
iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80

# Dan di FORWARD chain:
iptables -A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp --dport 80 -j ACCEPT

Traffic dari luar masuk ke port 8080 host → di-DNAT ke 172.17.0.2:80 (container) → diteruskan ke container. Source IP asli hilang (diganti IP bridge) kecuali kamu pakai mode host network.

Custom Bridge — DNS Otomatis #

docker network create my-net
docker run -d --name api --network my-net myapi
docker run -d --name db --network my-net postgres

Di custom network, container bisa saling menyebut dengan nama (api, db), bukan IP. Docker menjalankan embedded DNS server yang resolve nama container ke IP-nya. DNS otomatis hanya bekerja di custom network — di default bridge, container harus resolve IP lewat external DNS (atau pakai --link yang sudah deprecated). Selalu gunakan custom network untuk multi-container setup.


Security Layers — Container Bukan Sandbox Sempurna #

Container memberikan isolasi yang cukup baik untuk kebanyakan use case, tapi bukan sandbox sempurna seperti VM. Untuk production, kamu perlu menambahkan beberapa lapis keamanan di atas isolasi default namespace.

Lima Lapis Keamanan Container #

flowchart TB
    L0["Hardware/kernel"]
    L1["L1: Namespace (isolasi view)"]
    L2["L2: cgroup (isolasi resource)"]
    L3["L3: Capability (potong privilege)"]
    L4["L4: Seccomp (filter syscall)"]
    L5["L5: AppArmor/SELinux (MAC)"]

    L0 --> L1 --> L2 --> L3 --> L4 --> L5

1. Namespace — Isolasi View (Sudah Default) #

Memberikan container “view” sendiri dari PID, network, filesystem, dll. Ini adalah fondasi yang sudah otomatis diaktifkan.

2. cgroup — Isolasi Resource (Sudah Default) #

Membatasi CPU, memory, I/O. Default tidak ada limit — kamu harus set eksplisit.

3. Linux Capabilities — Potong Privilege #

Linux capabilities memecah hak root menjadi banyak kemampuan kecil. Container default masih punya banyak capability yang sebenarnya tidak dibutuhkan.

# Drop semua capability, tambahkan hanya yang dibutuhkan
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE nginx
# Container masih bisa bind port < 1024 (NET_BIND_SERVICE)
# Tapi tidak bisa mount filesystem, load module, dll
# ANTI-PATTERN: jalankan dengan semua capability
docker run --privileged nginx
# Container punya AKSES PENUH ke host (semua capability,
# akses ke /dev, akses ke kernel module, dll)
# Hanya untuk kasus sangat spesifik (Docker-in-Docker, dll)

# BENAR: drop semua, tambahkan hanya yang dibutuhkan
docker run --cap-drop=ALL --cap-add=CHOWN --cap-add=NET_BIND_SERVICE nginx

4. Seccomp — Filter System Call #

Seccomp (Secure Computing Mode) membatasi system call apa saja yang boleh dipanggil container. Docker menyediakan default seccomp profile yang allow system call umum, deny yang berbahaya.

# Cek profile default yang aktif
docker info | grep "Security Options"
# Output: seccomp
# Profile: builtin (Docker default)

# Jalankan dengan profile custom
docker run --security-opt seccomp=/path/to/profile.json nginx

Profile seccomp adalah JSON yang mendaftar syscall mana yang allowed, denied, atau trap. Contoh snippet:

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": ["read", "write", "exit", "exit_group", "open", "close"],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

5. AppArmor / SELinux — Mandatory Access Control #

AppArmor (Debian/Ubuntu) dan SELinux (RHEL/CentOS/Fedora) adalah mandatory access control (MAC) yang menambahkan policy file di atas kontrol tradisional Unix. Mereka memberikan lapisan keamanan tambahan dengan mendefinisikan secara eksplisit apa yang boleh dilakukan setiap binary.

# AppArmor profile untuk container
docker run --security-opt apparmor=docker-default nginx

# SELinux label
docker run --security-opt label=type:container_t nginx
Waspada: mengaktifkan SELinux di host tapi tidak men-disable untuk container sering menyebabkan masalah permission yang membingungkan. Jika kamu menjalankan RHEL/CentOS dengan SELinux enforced, pelajari label container (:Z dan :z untuk bind mount) atau kamu akan menghabiskan waktu berjam-jam debug “permission denied” misterius.

Perbandingan dengan VM Security #

Aspek Container + hardening Virtual Machine
Kernel attack surface Shared dengan host (risk) Terpisah per VM (aman)
Defense in depth Perlu konfigurasi eksplisit Built-in by hypervisor
Eksposur surface Kecil (minimal image) Besar (full OS)
CVE patching Patch host = patch semua container Patch per VM
Blast radius jika compromised Container root (mungkin host root) VM terpisah

Container dengan hardening yang tepat (rootless, read-only FS, capability minimal, seccomp, AppArmor) cukup aman untuk production multi-tenant. Tapi butuh effort untuk setup; VM aman by default (lewat hypervisor).


Alur Lengkap: Apa yang Terjadi Saat docker run #

Sekarang kita rangkum semua pembahasan di atas dengan menelusuri satu perintah end-to-end: docker run -d -p 8080:80 --memory=256m --cpus=0.5 --name web nginx:latest.

sequenceDiagram
    participant U as Terminal
    participant CLI as docker CLI
    participant D as dockerd
    participant CD as containerd
    participant RC as runc
    participant K as Linux Kernel
    participant R as Registry

    U->>CLI: docker run -d -p 8080:80 --memory=256m --cpus=0.5 --name web nginx:latest
    CLI->>D: POST /containers/create<br/>(name, image, port, limits)
    D->>D: validasi parameter
    D->>R: HEAD /v2/nginx/manifests/latest
    R-->>D: 200 OK (manifest info)
    D->>D: cek image cache lokal
    alt image belum ada
        D->>R: GET manifest + layers
        R-->>D: manifest + layer blobs
        D->>D: extract layer ke image storage
    end
    D->>D: generate container ID
    D->>D: setup cgroup dir + tulis memory/CPU limit
    D->>D: setup iptables rule (DNAT 8080→80)
    D->>D: create veth pair (siap di-attach saat container start)
    D->>CD: CreateContainer (gRPC)
    CD->>CD: snapshot writable layer (OverlayFS)
    CD->>CD: prepare OCI bundle (config.json, rootfs)
    CD->>CD: setup cgroup v2 entries
    CD->>RC: fork+exec runc
    RC->>K: clone(CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWUSER)
    K-->>RC: new namespace created
    RC->>K: mount overlay filesystem
    RC->>K: pivot_root ke rootfs container
    RC->>K: setup network namespace (move veth ke dalam)
    RC->>K: apply seccomp profile
    RC->>K: apply capability drops
    RC->>K: execve(/nginx, ["nginx", "-g", "daemon off;"])
    K-->>RC: nginx process running (PID 1 di namespace-nya)
    RC-->>CD: container started
    CD-->>D: success
    D-->>CLI: container ID
    CLI-->>U: print container ID

Delapan tahap yang terjadi:

  1. CLI parse & forwarddocker CLI mem-parse flag, menyusun JSON request sesuai Docker REST API, lalu mengirim ke daemon lewat /var/run/docker.sock.

  2. Daemon validasidockerd menerima request, validasi parameter (port conflict check, image name valid, dll).

  3. Image resolution — daemon cek cache lokal. Jika tidak ada, ia menarik manifest dan layer dari registry default (Docker Hub) lewat Docker Registry HTTP API v2.

  4. Container spec — daemon menyusun container specification lengkap: image mana, command apa, env var apa, port mapping, resource limit, security options.

  5. Resource setup — daemon membuat cgroup entry di /sys/fs/cgroup/<controller>/docker/<id>/ dan menulis limit. Untuk networking, daemon membuat veth pair dan iptables rules.

  6. Runtime delegation — daemon meneruskan spec ke containerd (gRPC), yang menyiapkan OCI bundle (config.json, rootfs directory). containerd lalu memanggil runc (fork+exec).

  7. Namespace creationrunc melakukan system call clone() dengan flag-flag namespace (CLONE_NEWNS, CLONE_NEWPID, CLONE_NEWNET, dst). Kernel membuat namespace baru dan child process lahir di dalamnya.

  8. Container start — di dalam namespace baru, runc melakukan mount overlay filesystem, pivot_root ke rootfs container, apply seccomp + capabilities, lalu execve("/nginx"). Proses nginx menjadi PID 1 di namespace-nya. Port 80 di namespace container ter-bridge ke port 8080 di host lewat iptables DNAT.

Semua terjadi dalam hitungan detik (untuk image cached: milidetik). Tidak ada boot sequence OS, tidak ada init system, tidak ada hypervisor. Container adalah proses yang dipersiapkan dengan teliti oleh kernel.

Tujuh Prinsip Kerja Docker #

Sekarang setelah kita membedah setiap komponen, mari kita rangkum dalam prinsip-prinsip yang menjelaskan mengapa Docker bekerja seperti itu.

flowchart LR
    P1["1. Container adalah<br/>proses Linux biasa"]
    P2["2. Isolasi = namespace<br/>+ cgroup, bukan VM"]
    P3["3. Image = layered<br/>filesystem (read-only)"]
    P4["4. Container = image<br/>+ writable layer (CoW)"]
    P5["5. Networking = veth<br/>+ bridge + iptables"]
    P6["6. Security = berlapis<br/>(ns, cgroup, cap, seccomp, MAC)"]
    P7["7. Standar OCI =<br/>runtime interchangeable"]
    P1 --> P2 --> P3 --> P4 --> P5 --> P6 --> P7

Cara mengingat: Docker bukan “mesin virtual mini” — Docker adalah orkestra Linux kernel yang diberi API bagus. Semua fitur yang membuat container “terasa berbeda” (isolasi, persistence, network) sebenarnya adalah fitur kernel Linux yang sudah ada sejak lama. Docker hanya membuat fitur-fitur ini accessible untuk developer.


Ringkasan #

  • Container adalah proses Linux biasa dengan namespace, cgroup, dan view filesystem khusus. Tidak ada hypervisor, tidak ada boot sequence, tidak ada VM. Inilah yang membuat container start dalam milidetik–detik, bukan menit.
  • Namespaces memberikan isolasi view: PID (container lihat PID sendiri), NET (NIC virtual), MNT (filesystem sendiri), UTS (hostname), IPC (tidak bisa signal ke host), USER (UID mapping), CGROUP (cgroup view). Tujuh namespace bekerja bersama menciptakan ilusi “sistem sendiri”.
  • cgroups memberikan isolasi resource: CPU, memory, I/O, PIDs, devices. Setiap controller dipasang ke filesystem pseudo, dan limit ditulis sebagai file. Kernel enforce limit secara real-time. Selalu set --memory dan --cpus di production.
  • Union filesystem (OverlayFS) menggabungkan banyak image layer (read-only) dengan container layer (read-write) menjadi satu mount point. Copy-on-write membuat perubahan runtime di-copy ke upperdir; file asli di lowerdir tetap utuh. Inilah yang membuat image kecil, build cepat, dan container efisien.
  • Networking dibangun dari veth pair (cable virtual), bridge (switch virtual), dan iptables (NAT/port mapping). Default bridge (docker0) menghubungkan semua container di host. Custom network menambahkan DNS otomatis dan isolasi.
  • Security berlapis: namespace (view) + cgroup (resource) + capabilities (potong privilege) + seccomp (filter syscall) + AppArmor/SELinux (MAC). Container dengan hardening cukup aman untuk production; tanpa hardening, ia setara root di host.
  • Alur docker run melewati 8 tahap: CLI parse → daemon validasi → image resolution → spec → resource setup → runtime delegation → namespace creation → container start. Semua terjadi di level kernel, tanpa hypervisor.
  • Standar OCI membuat runtime interchangeable: runc bisa diganti crun (lebih cepat) atau youki (Rust). Image Docker bisa dijalankan di containerd, Podman, atau K8s CRI-O tanpa modifikasi.
  • Container ≠ sandbox sempurna. Untuk multi-tenant, compliance ketat, atau workload yang butuh hardware isolation, pertimbangkan VM. Untuk kebanyakan cloud-native workload, container dengan hardening adalah pilihan yang benar.

← Sebelumnya: Registry   Berikutnya: File System & Layer →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact