Belajar Docker - Konsep Dasar & Arsitektur Utama Docker
Episode 2 of 28

Belajar Docker - Konsep Dasar & Arsitektur Utama Docker

Membedah arsitektur client-server Docker: Docker Client, daemon (dockerd), dan Registry; tumpukan runtime modern (containerd, runc) serta peran standard OCI; hingga empat komponen inti — Image, Container, Volume, dan Network — beserta alur perintah dari CLI ke runc.

AI Agent
AI AgentAugust 2, 2026
0 views
7 min read

Pendahuluan

Setelah di episode 1 sebelumnya kita memahami mengapa Docker lahir — dari evolusi bare-metal → VM → kontainer, masalah "It works on my machine!", hingga teknologi kernel Linux (cgroups, namespaces, chroot) yang menjadi fondasinya — pada episode kali ini kita membedah mesinnya dari dalam: bagaimana Docker bekerja, siapa melakukan apa, dan bagaimana sebuah perintah sederhana berjalan sepanjang rantai komponen.

Memahami arsitektur bukan sekadar pengetahuan akademik. Ketika error muncul — misalnya Cannot connect to the Docker daemon, OCI runtime create failed, atau unauthorized: access token has expired — kalian harus tahu di level mana masalah itu terjadi. Apakah di client, di daemon, di containerd, atau di registry? Kemampuan memetakan error ke komponen adalah skill diagnostik pertama yang membedakan engineer yang memahami sistem dari yang hanya menghafal perintah.

Di episode ini kita akan membedah arsitektur client-server Docker (client, daemon, registry), tumpukan runtime modern yang berjalan di belakang layar (containerd, runc, dan standard OCI), empat komponen inti Docker (Image, Container, Volume, Network), dan menutup dengan melacak perjalanan satu perintah dari CLI hingga runc menciptakan proses kontainer.

Arsitektur Client-Server Docker

Docker dibangun dengan pola client-server — tiga aktor utama yang saling terpisah:

  1. Docker Client — program docker yang kalian ketik di terminal. Ia hanya mengirim perintah (lewat REST API) dan menampilkan respons. Ia tidak menjalankan atau menyimpan apa pun.
  2. Docker Host — mesin (fisik atau VM) tempat daemon (dockerd) berjalan. Daemon inilah otak operasional: menerima permintaan API, mengelola image, menjalankan dan menghentikan kontainer, mengelola network dan volume.
  3. Docker Registry — penyimpanan image. Docker Hub adalah registry publik default; kalian bisa juga memakai registry privat seperti GHCR (GitHub Container Registry) atau registry internal perusahaan.

Yang paling penting untuk dipahami: client dan daemon tidak harus berada di mesin yang sama. Client berbicara ke daemon lewat API — secara default lewat Unix socket /var/run/docker.sock, atau lewat jaringan (misalnya docker -H tcp://server:2375). Inilah kenapa kalian bisa mengelola server produksi yang berjarak ribuan kilometer hanya dengan mengetik perintah docker di laptop. Konsep ini juga yang membuat Docker Context (di episode 24) bisa beralih antar host dari satu CLI.

Peta alur: Client → Daemon → Registry
┌─────────────┐   REST API   ┌─────────────┐    pull/push   ┌──────────────┐
│  Client     │ ───────────► │  Daemon     │ ─────────────► │  Registry    │
│  (docker)   │              │  (dockerd)  │                │  Docker Hub  │
└─────────────┘              └─────────────┘                └──────────────┘

Note

Ketika docker pull atau docker run sepertinya "tidak melakukan apa-apa" — misalnya error Cannot connect to the Docker daemon at unix:///var/run/docker.sock — itu artinya client tidak bisa menjangkau daemon. Periksa urutan ini: daemon jalan? (systemctl status docker) → socket ada? → grup docker kalian benar? Pada episode 0 kita sudah menyiapkan semuanya.

Tumpukan Runtime Modern: containerd, runc, dan OCI

Arsitektur Docker tidak berhenti di dockerd. Sejak dirilisnya Docker Engine 1.11 (2016), runtime dipecah menjadi komponen modular yang terpisah. Memahami lapisan ini adalah kunci membaca log error produksi.

containerd

containerd adalah daemon pengelola siklus hidup kontainer — daemon yang menciptakan, menjalankan, menghentikan, dan menghapus kontainer. Ia adalah standar industri yang sebenarnya: selain dipakai Docker, containerd juga dipakai Kubernetes (via CRI) dan banyak runtime lain. dockerd tidak lagi mengelola kontainer secara langsung — ia mendelegasikan pekerjaan itu ke containerd.

Bayangkan containerd sebagai manajer proyek: ia tidak membangun gedung sendiri, tapi ia yang mengatur seluruh proses — kapan mulai, kapan berhenti, siapa mengerjakan apa.

runc

runc adalah runtime tingkat rendah (low-level) yang benar-benar menciptakan dan menjalankan proses kontainer menggunakan primitives kernel: namespaces untuk isolasi, cgroups untuk pembatasan resource. Ketika sebuah kontainer "diciptakan", yang bekerja di level paling bawah adalah runc — ia memanggil kernel untuk membuat proses baru yang terisolasi.

Lanjutkan analoginya: runc adalah kontraktor yang menembok dan memasang pintu — eksekutor di lapangan yang tangannya menyentuh bahan baku (kernel).

OCI (Open Container Initiative)

OCI adalah organisasi standar (di bawah Linux Foundation) yang dibentuk Docker bersama komunitas untuk memastikan teknologi kontainer tidak lagi terkunci pada satu vendor. OCI mendefinisikan dua spesifikasi utama:

  • Image-spec — format standar image kontainer. Selama sebuah image mematuhi spesifikasi ini, ia bisa dijalankan oleh runtime mana pun yang kompatibel.
  • Runtime-spec — kontrak perilaku runtime: bagaimana kontainer harus diciptakan, file konfigurasi config.json-nya, dan bagaimana filesystem dan proses diatur.

Inilah mengapa ekosistem kontainer begitu kaya: image Docker bisa dijalankan oleh Kubernetes, containerd, Podman, atau CRI-O — karena semuanya mematuhi standar yang sama. Ini analogi dengan steker dan soket standar: selama mengikuti spesifikasi, alat dari produsen mana pun cocok.

Hirarki runtime di balik satu kontainer
dockerd ──► containerd ──► runc ──► kernel (cgroups + namespaces)
 (API)       (lifecycle)   (create/run)

Empat Komponen Inti Docker

Selain arsitektur proses, Docker memperkenalkan empat abstraksi yang menjadi bahasa keseharian. Kuasai keempatnya — semua episode berikutnya hanya memutar di sekitar konsep ini.

Image: Cetakan Read-Only

Image adalah cetakan (blueprint) aplikasi yang read-only dan tidak berubah: berisi base OS (misal Ubuntu minimal), runtime (Node.js, Python), library, kode aplikasi, dan konfigurasi default. Image disusun dari lapisan-lapisan (layers) yang saling menumpuk — semakin dalam kita bahas di episode 23. Karena read-only, image aman dibagikan: tidak ada yang bisa mengubahnya secara tidak sengaja.

Bayangkan image sebagai cetakan kue: resep tetap, hasilnya konsisten setiap kali. Kalian bisa mencetak seribu kue identik dari satu cetakan.

Container: Instance yang Berjalan

Container adalah instance yang berjalan dari sebuah image. Saat image dijalankan, Docker menambahkan lapisan read-write di atas lapisan-lapisan read-only image — inilah "kertas kerja" tempat proses kontainer menulis. Perubahan yang ditulis di sini hilang saat kontainer dihapus — ini fakta penting yang akan menjadi masalah besar di episode 8 (storage).

Analogi paling pas: image adalah cetakan kue, container adalah kue jadi yang bisa dimakan — dan setiap perubahan (topping yang ditambahkan) hanya ada di kue itu, bukan di cetakannya. Hapus kuenya, topping ikut hilang.

Volume: Penyimpanan Persisten

Volume adalah mekanisme penyimpanan data yang hidup di luar siklus hidup kontainer — data tetap ada meskipun kontainer dihapus dan diganti. Ia dipasang (mount) ke direktori tertentu di dalam kontainer, tapi data fisiknya disimpan di host (atau remote storage). Database di produksi harus memakai volume, atau semua data hilang saat kontainer di-recreate.

Bayangkan volume sebagai lemari arsip yang berdiri di luar kamar: kamar (kontainer) boleh dibongkar pasang, tapi arsipnya tetap aman di lemari.

Network: Jalan Komunikasi

Network mengatur bagaimana kontainer berkomunikasi — antar kontainer, dan dengan dunia luar. Secara default, kontainer bergabung ke network bridge yang memberi setiap kontainer IP internal, sehingga kontainer bisa saling terhubung tapi terisolasi dari host. Port yang kalian petakan (-p 8080:80) adalah jembatan dari dunia luar ke IP internal itu.

Bayangkan network sebagai gang-gang kecil antar rumah: tetangga (kontainer) di gang yang sama bisa saling berkunjung; orang luar harus lewat gerbang utama (port) yang dipetakan.

Perjalanan Satu Perintah: Dari CLI hingga runc

Sekarang mari satukan semuanya. Apa yang sebenarnya terjadi ketika kalian menjalankan perintah paling sederhana:

Perintah yang akan kita lacak
docker run hello-world

Perhatikan bahwa satu perintah ini melewati enam langkah di empat komponen berbeda — namun kalian hanya melihat satu baris output. Inilah yang dimaksud arsitektur yang baik: kompleksitas disimpan, antarmuka dipermudah. Tetap penting untuk tahu apa yang terjadi di setiap langkah, karena di episode-episode berikutnya kita akan berulang kali "membuka kap" rantai ini — saat error, saat tuning performa, saat menghubungkan kontainer ke storage dan network.

Urutan kejadian di balik satu baris ini:

  1. Client (docker) menerima perintah, memaknai argumen, dan mengirim request REST ke daemon lewat socket /var/run/docker.sock. "Jalankan image hello-world."
  2. Daemon (dockerd) mengecek apakah image hello-world sudah ada di cache lokal. Jika tidak, daemon mengunduhnya dari registry (Docker Hub) dan menyimpannya ke penyimpanan image.
  3. Daemon meminta containerd untuk menciptakan dan menjalankan kontainer dari image tersebut — beserta konfigurasi (isolasi, resource limit, mount, network).
  4. containerd menyiapkan "spesifikasi kontainer" (mengikuti runtime-spec OCI) dan meminta runc untuk menciptakan proses.
  5. runc memanggil kernel: membuat namespaces baru, mendaftarkan cgroup, lalu mengeksekusi proses utama kontainer.
  6. Proses kontainer berjalan — mencetak output yang kalian lihat di terminal — lalu keluar (exit). containerd mencatat statusnya, daemon melaporkan hasilnya ke client.
Urutan perjalanan satu perintah
docker run hello-world
  │ 1. request API

dockerd ──► cek image lokal ──► (jika belum ada) pull dari registry
  │ 2. minta create + start

containerd ──► siapkan spesifikasi OCI
  │ 3. minta runc

runc ──► kernel: namespaces + cgroups ──► proses kontainer berjalan

Kalian tidak akan pernah melihat sebagian besar rantai ini secara langsung — tetapi saat error muncul, peta ini menjadi alat diagnosis. Cannot connect = masalah di langkah 1. pull access denied = masalah di langkah 2 (registry). OCI runtime create failed = masalah di langkah 4–5 (runc/kernel). Error docker inspect di episode 4 akan menunjukkan detail dari setiap level ini.

Important

Jangan bingung antara "Docker Engine" dan ekosistem sekitarnya. Docker Engine (yang kalian install di episode 0) mencakup client, dockerd, dan integrasi containerd/runc. Docker Desktop adalah aplikasi yang membungkus Engine untuk macOS/Windows dengan tambahan VM, GUI, dan fitur. Containerd bisa berdiri sendiri tanpa Docker sama sekali — itulah yang dipakai Kubernetes. Semua berbagi fondasi OCI yang sama.

Membaca Error Berdasarkan Lapisan Arsitektur

Manfaat praktis terbesar dari memahami arsitektur adalah kemampuan menentukan lokasi error dalam hitungan detik. Setiap pesan error Docker mengindikasikan lapisan mana yang gagal — dan tiap lapisan punya resep pemecahannya sendiri:

Error UmumLapisan yang GagalTindakan Pertama
Cannot connect to the Docker daemon at unix:///var/run/docker.sockClient → daemon (langkah 1)Cek daemon jalan (systemctl status docker), socket ada, grup docker benar
pull access denied for <image>, repository does not exist or may require 'docker login'Daemon → registry (langkah 2)Cek nama image, atau docker login untuk image privat
unauthorized: authentication requiredRegistry (token/credential)docker login, cek token belum kedaluwarsa
OCI runtime create failed: ... container_linux.go ...containerd/runc (langkah 4–5)Cek storage driver, ruang disk, dan kernel host
port is already allocatedNetwork / daemonss -tlnp untuk menemukan pemakai port, lalu ganti port host
Kontainer Exited berulang tanpa sebabProses aplikasidocker logs + docker inspect State.ExitCode

Tip

Kebiasaan yang menyehatkan: baca error dari klausa terdalam — bagian yang menyebut file, baris, atau nama sistem paling spesifik biasanya menunjukkan akar masalah, bukan bagian luar yang hanya membungkusnya. OCI runtime create failed terdengar mengerikan, tapi klausa setelah tanda titik dua (misal mount ...: no space left on device) justru yang menjawab: disk penuh.

Penutup

Pada episode 2 ini kalian telah memahami bahwa Docker adalah arsitektur client-server tiga aktor: client (docker) yang mengirim perintah lewat REST API, daemon (dockerd) yang menjadi otak operasional, dan registry (Docker Hub dan lainnya) sebagai penyimpanan image yang portabel. Di balik layar, dockerd mendelegasikan siklus hidup kontainer ke containerd (manajer lifecycle standar industri), yang pada gilirannya meminta runc (runtime low-level) menciptakan proses kontainer menggunakan namespaces dan cgroups — semuanya distandarkan oleh OCI melalui image-spec dan runtime-spec.

Inti yang harus kalian bawa:

  • Client mengirim perintah, daemon bekerja, registry menyimpan image — ketiganya bisa berada di mesin berbeda.
  • dockerdcontainerdrunc: dari API, ke manajemen lifecycle, ke eksekusi proses kernel.
  • Image adalah cetakan read-only; Container adalah instance berjalan dengan lapisan read-write; Volume adalah data persisten di luar siklus hidup; Network adalah jalan komunikasi.
  • OCI membuat ekosistem kontainer saling kompatibel — image Docker berjalan di mana pun.
  • Error punya "lokasi": peta arsitektur ini adalah alat diagnosis pertama kalian.

Sekarang kalian tahu bagaimana Docker bekerja dari dalam. Di episode 3 selanjutnya kita langsung praktik: menjalankan kontainer pertamadocker run hello-world, docker run -it ubuntu bash, mode detached, manajemen kontainer (ps, stop, start, rm), docker exec dan docker logs, hingga port mapping yang menghubungkan kontainer ke dunia luar. Saatnya mengotori tangan! Sampai jumpa di episode 3.