Kita sudah memahami apa itu container dan bagaimana container berdiri di samping mesin virtual. Sekarang mari kita buka kap mesinnya: ketika kita mengetik docker run di terminal, tidak ada sihir yang terjadi — ada sekumpulan komponen yang bekerja berlapis dan saling berbicara melalui antarmuka yang jelas. Memahami arsitektur ini membuat galat di masa depan terasa masuk akal, karena kita tahu komponen mana yang sedang bersuara, dan membuat istilah seperti containerd atau runtime tidak lagi terdengar asing. Chapter ini membedah arsitektur client-server Docker dari CLI di ujung jari sampai proses container di dalam kernel.
Arsitektur Client-Server #
Docker berarsitektur client-server. Perintah docker yang kita ketik di terminal hanyalah klien CLI yang ringan: klien tidak membuat container maupun mengunduh image dengan caranya sendiri. Semua pekerjaan berat dilakukan dockerd — daemon Docker yang berjalan di latar belakang — dan klien berbicara dengan daemon tersebut melalui REST API yang secara default dapat diakses lewat Unix socket /var/run/docker.sock, atau lewat TCP untuk koneksi jarak jauh.
Di dalam host, dockerd pun tidak bekerja sendirian. Pengelolaan siklus hidup container didelegasikan ke containerd, runtime tingkat tinggi yang juga menjadi standar di luar Docker — Kubernetes memakainya juga. Untuk benar-benar melahirkan proses container, containerd memanggil runc: runtime tingkat rendah yang membentuk namespace dan cgroups sesuai spesifikasi OCI, lalu menyerahkan proses yang sudah hidup kembali ke containerd untuk diawasi. Pada sisi distribusi image berdiri registry seperti Docker Hub yang menyimpan image siap unduh. Arsitektur berlapis inilah yang digambarkan diagram berikut.
Diagram Arsitektur #
Mari kita telaah arti setiap panah pada diagram di atas:
- docker CLI ke dockerd — satu-satunya jalur komunikasi klien adalah REST API; klien boleh berada di mesin yang sama dengan daemon maupun di mesin jauh yang mengarah ke daemon lewat jaringan.
- dockerd ke registry dan sebaliknya — saat image belum ada di lokal, dockerd meminta manifest dan layer image dari registry (pull); ke arah sebaliknya, hasil build dikirim ke registry untuk disimpan (push).
- dockerd ke containerd — daemon tidak memegang container dengan tangannya sendiri; seluruh siklus hidup container diserahkan ke containerd.
- containerd ke runc — untuk melahirkan proses, containerd menyiapkan rootfs dan konfigurasi proses, lalu memanggil runc.
- runc ke proses container — runc membentuk isolasi lalu mundur setelah proses hidup; containerd lah yang terus mengawasi proses tersebut melalui komponen shim.
Perjalanan docker run nginx #
Teori di atas akan lebih melekat jika kita telusuri satu perintah nyata. Mari kita ikuti perjalanan docker run nginx — perintah yang akan sering kita pakai sepanjang Course ini — dalam lima langkah:
- CLI mengirim permintaan — klien
dockermengurai argumennginx, lalu mengirim permintaan pembuatan container ke dockerd melalui REST API. - Daemon menarik image — dockerd memeriksa penyimpanan image lokal; karena image nginx belum ada, daemon menghubungi registry Docker Hub, membaca manifest, dan mengunduh layer-layer yang belum dimiliki.
- containerd menyiapkan rootfs — dockerd menyerahkan pekerjaan ke containerd; containerd menyusun rootfs dari layer image dan menyiapkan konfigurasi proses yang akan dijalankan.
- runc menghidupkan proses — containerd memanggil runc; runc membentuk namespace dan cgroups, memulai nginx sebagai proses dengan PID 1 di dalam container, lalu runc selesai dan kontrol kembali ke containerd.
- CLI menerima hasil — daemon mengirim ID container kembali ke CLI dan mengalirkan keluaran aplikasi ke terminal; nginx kini hidup sebagai proses terisolasi di host.
Membedah docker version #
Perintah docker version membaca versi setiap komponen tanpa menyentuh container apa pun, sehingga aman dijalankan kapan saja. Outputnya sekaligus menjadi foto keluarga arsitektur yang baru kita bahas: bagian Client untuk CLI beserta plugin-nya, dan bagian Server untuk daemon beserta runtime di bawahnya. Mari kita jalankan:
$ docker versionOutput yang Dihasilkan:
Client: Docker Engine - Community
Version: 29.9.0
OS/Arch: linux/amd64
Context: default
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.28.0
compose: Docker Compose (Docker Inc.)
Version: v5.6.0
Server: Docker Engine - Community
Engine:
Version: 29.9.0
API version: 1.52
OS/Arch: linux/amd64
containerd:
Version: 2.1.4
runc:
Version: 1.3.2Output aslinya sedikit lebih panjang — setiap plugin juga mencantumkan baris Path, dan bagian Server mencantumkan Git commit serta waktu build — tetapi baris-baris tersebut kita potong karena tidak berpengaruh pada pembahasan. Mari kita telaah bagian-bagian pentingnya:
- Client Version 29.9.0 — versi CLI yang terpasang di mesin kita; versi CLI tidak harus sama dengan versi daemon, karena keduanya berkomunikasi lewat REST API yang dirancang kompatibel antar versi.
- Context default — context menentukan daemon mana yang dituju CLI; cara memiliki banyak context untuk banyak daemon sekaligus kita bahas pada Chapter Memahami Docker Context.
- Plugins buildx dan compose — dua plugin CLI yang menyatu pada perintah
docker:docker buildxuntuk build modern dandocker composeuntuk mengelola stack multi-container. - Server Engine 29.9.0 dengan API version 1.52 — ini versi dockerd dan REST API-nya; klien lama yang hanya memahami API lebih rendah tetap dapat diajak bicara oleh daemon baru.
- containerd 2.1.4 dan runc 1.3.2 — bukti nyata arsitektur berlapis pada sisi Server; keduanya adalah komponen terpisah yang diawasi dockerd, persis seperti diagram kita di atas.
Perintah ini juga berguna saat diagnosis: jika daemon mati, docker version hanya menampilkan bagian Client disertai galat koneksi. Kita akan sering memakainya lagi pada Section Instalasi dan Konfigurasi saat memverifikasi pemasangan.
Peran Setiap Komponen #
| Komponen | Peran |
|---|---|
| docker CLI | Klien baris perintah yang menerima input kita dan menerjemahkannya menjadi panggilan REST API |
| REST API | Antarmuka resmi daemon — semua alat di ekosistem Docker berbicara melalui API ini |
| dockerd | Daemon inti yang mengelola image, container, network, dan volume |
| containerd | Runtime tingkat tinggi yang mengawasi siklus hidup container dari lahir sampai mati |
| runc | Runtime tingkat rendah yang membentuk proses container sesuai spesifikasi OCI |
| registry | Layanan penyimpanan dan distribusi image, contohnya Docker Hub |
Enam komponen ini tidak perlu kita hafal urutan panggilannya setiap saat. Yang penting adalah ingat pembagiannya: CLI di sisi pengguna, dockerd sebagai pintu gerbang sekaligus otak, containerd dan runc sebagai pelaksana di level proses, serta registry di sisi distribusi. Pembagian peran inilah yang membuat Docker tetap rapi meski ekosistemnya terus membesar.
Namespace dan Cgroups #
Kita berulang kali menyebut namespace dan cgroups sebagai fondasi isolasi container; saatnya melihat apa saja yang sebenarnya diisolasi. Kernel Linux menyediakan beberapa jenis namespace, dan Docker mengaktifkannya secara otomatis setiap kali container dibuat:
| Namespace | Yang diisolasi |
|---|---|
| pid | Nomor dan hierarki proses — container melihat prosesnya sendiri, dan proses utamanya menjadi PID 1 |
| net | Kartu jaringan, tabel routing, dan port — container memiliki stack jaringan sendiri |
| mnt | Titik mount dan sistem berkas yang terlihat oleh proses |
| uts | Hostname dan nama domain milik container |
| ipc | Fasilitas komunikasi antar proses seperti shared memory dan semaphore |
| user | Pemetaan UID dan GID — proses root di container dapat dipetakan ke pengguna biasa di host |
Keenam namespace inilah yang membuat proses nginx pada section sebelumnya merasa hidup di mesinnya sendiri. Sementara namespace membatasi apa yang dilihat proses, cgroups membatasi berapa banyak resource yang boleh dipakai proses tersebut. Docker menyediakan flag siap pakai untuk kebutuhan ini: --cpus membatasi jumlah CPU dan --memory membatasi besaran memori sebuah container. Pembahasan penuh pembatasan resource menunggu Section Manajemen Resource.
Dengan arsitektur dan fondasi isolasi yang kini jelas, satu pertanyaan praktis tinggal menggantung: perangkat-perangkat ini kita dapatkan dari mana, dan dalam bentuk paket apa? Chapter Docker Engine dan Docker Desktop menjawabnya dengan membandingkan dua jalur distribusi resmi Docker.
Referensi #
- Docker Overview — diagram arsitektur client-server pada dokumentasi resmi.
- Use the Docker CLI — referensi resmi perintah docker CLI.
- Open Container Initiative — spesifikasi image dan runtime container yang diikuti runc.