Penutup Section Docker dalam Pengembangan menutup buku latihan dengan daftar utang yang jujur: sepanjang perjalanan itu container development kita menyala sebagai root, kredensial duduk di berkas .env berformat teks polos, debug port diterbitkan ke jaringan lokal begitu saja, dan image ditarik dari registry mana pun tanpa diperiksa isinya. Section Keamanan Docker dibuka justru untuk melunasi daftar itu — bukan dengan hafalan flag, melainkan dengan memahami pagar yang sebenarnya kita andalkan. Chapter ini meletakkan satu kebenaran fundamental sebagai fondasi seluruh section: container bukan mesin virtual, dan semua yang memisahkannya dari host adalah fitur-fitur kernel Linux yang sama yang juga melayani proses host biasa.
Container Bukan Mesin Virtual #
Mesin virtual memvirtualisasi perangkat keras. Hypervisor menyajikan CPU, memori, dan disk tiruan; di atas perangkat tiruan itu terpasang sistem operasi lengkap dengan kernel miliknya sendiri; dan batas antara guest dengan host dijaga oleh hypervisor — lapisan perangkat lunak yang sengaja dibuat kecil dan kaku supaya permukaan serangannya sempit. Container tidak memiliki lapisan semacam itu. Container adalah proses biasa di host: sebuah proses yang membawa atribut pembatas sejak detik pertama ia dilahirkan oleh runtime.
Konsekuensinya langsung terasa pada arsitektur. Ketika sebuah proses di dalam container membuka berkas, mengirim paket jaringan, atau mengalokasikan memori, proses tersebut mengirim syscall — dan syscall itu dikerjakan oleh kernel host, baris kode kernel yang sama yang saat ini juga melayani proses SSH, editor teks, dan daemon Docker di host. Tidak ada penerjemah dan tidak ada hypervisor di tengah jalur. Kernel dibagi — dan karena dibagi, kernel sekaligus menjadi permukaan serangan yang dibagi antara host dan semua container yang berjalan di atasnya.
| Aspek | Mesin virtual | Container |
|---|---|---|
| Kernel | kernel sendiri di atas hypervisor | kernel host yang sama |
| Bentuk dasar | sistem operasi lengkap | proses biasa dengan atribut pembatas |
| Isolasi dijaga oleh | hypervisor | namespace, cgroups, capabilities, seccomp, LSM |
| Bobot dan kecepatan | gigabyte, menyala belasan detik | megabyte, menyala milidetik |
| Bila isolasinya tembus | penyerang mendarat di guest OS | penyerang mendarat di host |
Baris terakhir tabel itulah alasan section ini eksis. Celah pada kernel yang bisa dieksploitasi oleh proses host biasa umumnya juga bisa dicapai dari dalam container, karena bagi kernel keduanya hanyalah proses yang membawa atribut berbeda. Pada mesin virtual, jalur yang sama harus menembus guest OS dan hypervisor lebih dulu sebelum menyentuh host. Isolasi container nyata dan bekerja setiap hari di jutaan server — tetapi jaminannya berbeda jenis, bukan sekadar berbeda derajat.
Lima Lapisan Isolasi #
Docker tidak membangun pagar dari nol; ia menumpuk lima mekanisme kernel Linux yang sudah lama ada. Masing-masing menjawab pertanyaan yang berbeda, dan kekeliruan paling umum soal keamanan container biasanya bermula dari mencampur kelima jawaban itu menjadi satu kata kabur bernama “isolasi”.
| Lapisan | Pertanyaan yang dijawab | Apa yang diatur |
|---|---|---|
| Namespace | Apa yang dilihat container | proses, jaringan, mount, dan user tampak sebagai dunia sendiri |
| Cgroups | Berapa resource yang boleh dipakai | kuota CPU, memori, dan IO dalam angka |
| Capabilities | Apa yang boleh dilakukan root | privilege root dipecah; sebagian dicabut dari container |
| Seccomp | Syscall mana yang diizinkan | filter yang menolak syscall berbahaya sebelum dikerjakan |
| LSM AppArmor dan SELinux | Policy tambahan apa yang berlaku | profil yang memeriksa operasi sensitif per program |
Diagram di atas menyusun kelima mekanisme sebagai cangkang berlapis di sekeliling proses, dengan satu panah menegaskan intinya: setiap syscall dari proses container harus melewati seluruh cangkang sebelum dikerjakan kernel host. Susunan cangkang adalah representasi konseptual defense in depth, bukan urutan pemeriksaan yang literal — seccomp dan LSM memeriksa di pintu syscall, capabilities diperiksa kernel saat eksekusi berlangsung, sementara namespace dan cgroups lebih menentukan pandangan serta jatah resource sejak proses lahir. Kita bedah kelima lapisan itu satu per satu.
Namespace Mengatur Apa yang Dilihat #
Namespace memotong pandangan. PID namespace membuat proses container melihat dirinya sebagai penghuni tunggal sebuah dunia — proses utamanya tampak sebagai PID 1 — padahal dari sisi host proses itu punya nomor PID biasa dan tampak di daftar proses host seperti proses lainnya. Network namespace memberi container antarmuka jaringan, alamat IP, dan tabel routing sendiri. Mount namespace memberi pohon filesystem sendiri, itulah sebabnya container melihat /usr milik imagenya, bukan /usr milik host. Penting dicatat: namespace tidak memberi atau mencabut daya — namespace hanya membatasi apa yang terlihat, dan kita sudah memanfaatkan mesin ini sejak Section Jaringan Container membahas network namespace.
Cgroups Mengatur Berapa yang Boleh Dipakai #
Cgroups membatasi jumlah, bukan jenis. Kuota CPU, plafon memori, dan batas IO yang kita setel lewat --memory dan --cpus pada Chapter CPU dan Memory Limit semuanya ditegakkan oleh cgroups di dalam kernel. Proses yang melampaui plafon memorinya dibunuh oleh kernel dengan sinyal SIGKILL — exit code 137 yang pernah kita diagnosa pada Chapter Debugging Container. Cgroups tidak peduli apa yang proses lihat dan tidak peduli proses itu root atau bukan; cgroups hanya menghitung berapa yang boleh dimakan.
Capabilities Mengatur Apa yang Boleh Dilakukan Root #
Sejak kernel Linux 2.2, kekuatan root yang dulu monolitis dipecah menjadi sekitar 38 capability — unit-unit privilege bernama seperti CHOWN, NET_BIND_SERVICE, atau SYS_ADMIN. Root di host memegang semuanya; root di dalam container hanya memegang 12 di antaranya, karena Docker mencabut sisanya sejak container lahir. Inilah lapisan yang menjelaskan mengapa root container bisa chown berkas tetapi tidak bisa mengubah jam sistem atau melakukan mount. Peta lengkap dua belas capability bawaan itu — beserta cara mencabut dan menambahnya — adalah materi Chapter Linux Capabilities yang menyusul.
Seccomp Menyaring Syscall Mana yang Diizinkan #
Seccomp adalah penjaga pintu paling depan: filter yang memeriksa nomor syscall sebelum syscall itu dikerjakan kernel. Docker memasang profil default yang memblokir puluhan syscall jarang-pakai namun berbahaya — misalnya syscall untuk memuat modul kernel atau mengganti kernel yang berjalan — syscall yang jarang dibutuhkan aplikasi normal namun sering dibutuhkan eksploit. Jika namespace membatasi pandangan dan capabilities membatasi hak, seccomp membatasi pintu masuknya sendiri. Profil default ini bisa dikustomisasi, dan mekanismenya kita bedah pada Chapter Seccomp, AppArmor, dan SELinux.
LSM Menambah Policy di Pintu Kernel #
LSM — Linux Security Modules — adalah kerangka hook di dalam kernel yang memungkinkan policy keamanan tambahan diperiksa pada operasi sensitif. Dua implementasi yang paling sering dijumpai adalah AppArmor, yang memeriksa profil per program berbasis path dan bawaan di keluarga Ubuntu, serta SELinux, yang bekerja dengan label pada objek dan bawaan di keluarga Red Hat. Docker memasang profil default untuk container di host yang mengaktifkan salah satunya, sehingga container mendapat pemeriksaan ekstra di luar namespace, capabilities, dan seccomp. Kedua sistem ini menyempurnakan cangkang kelima pada diagram di atas.
Rumus Kekuatan Root di Container #
Banyak pengguna terkejut saat pertama kali menyadari bahwa root di dalam container bukan root “palsu” atau root yang disimulasikan. Proses root container menjalankan syscall sungguhan pada kernel host dengan privilege sungguhan — yang menahannya hanyalah dua mekanisme yang sudah kita bedah. Kita padatkan menjadi satu rumus:
root di container = kekuatan penuh root di host, minus capabilities yang dicabut dan pandangan yang dibatasi namespace
Mari kita telaah tiga suku rumus tersebut satu per satu:
- “Kekuatan penuh root di host” — syscall yang dikirim proses root container dikerjakan kernel host dengan privilege level root yang nyata; tidak ada lapisan yang “menurunkan” daya syscall sebelum menyentuh kernel.
- “Minus capabilities yang dicabut” — dari sekitar 38 capability milik root host, container bawaan hanya membawa 12;
SYS_ADMIN,SYS_TIME,NET_ADMIN, dan kawan-kawannya absen, sehingga sebagian besar operasi administratif ditolak kernel denganOperation not permitted. - “Pandangan yang dibatasi namespace” — root container tidak melihat filesystem host, proses host, atau antarmuka jaringan host; namespace membatasi objek yang bisa dijangkau pandangan, meski dayanya tetap nyata.
- Implikasi praktisnya — hanya dua variabel inilah yang menahan root container: capabilities dan namespace; bendera
--privilegedyang akan kita bedah pada Chapter Privileged Container justru melonggarkan keduanya sekaligus.
Breakout Pernah Terjadi #
Rumus di atas bukan teori menakut-nakuti. Isolasi container pernah bolong secara nyata dan dipublikasikan dunia.
Karena itu pula dua lapisan paling dalam — seccomp dan LSM — punya peranan khusus: keduanya tetap menyaring syscall sekalipun seorang penyerang berhasil mendapat shell sebagai root di dalam container. Pagar yang paling berharga justru yang diuji setelah lapisan di depannya jatuh.
Dua Prinsip: Least Privilege dan Defense in Depth #
Seluruh praktik pada section ini bernaung di bawah dua prinsip. Yang pertama, least privilege: setiap proses berhak atas akses paling sedikit yang masih memungkinkan pekerjaannya selesai — bukan akses yang kebetulan lumayan. Aplikasi yang hanya menyajikan berkas statis tidak butuh kemampuan mengubah jam, menulis ke device, atau berbicara dengan kernel sebagai root. Yang kedua, defense in depth: jangan pernah bertaruh pada satu lapisan; lima cangkang pada diagram di atas bernilai justru karena satu lapisan yang tembus masih meninggalkan empat lapisan lain yang menahan.
Dua prinsip itu diterjemahkan menjadi praktik konkret yang tersebar di seluruh chapter section ini:
| Praktik keamanan | Chapter |
|---|---|
| Menjalankan proses sebagai user non-root | Menjalankan Container Non-Root |
| Mencabut capabilities yang tidak dipakai | Linux Capabilities |
Menolak bendera --privileged dan memakai alternatifnya | Privileged Container |
| Mengunci filesystem container | Read-Only Filesystem |
| Menyaring syscall dan memasang profil LSM | Seccomp, AppArmor, dan SELinux |
| Mengeluarkan rahasia dari image dan environment | Secret Management |
| Memindai kerentanan image | Image Scanning |
| Membuktikan asal-usul dan isi image | Image Provenance serta Supply Chain Security |
| Mengamankan akses ke docker.sock | Docker Socket Security |
Catatan Jujur: Lebih Terisolasi daripada Proses Biasa #
Setelah semua kabar buruk di atas, kalibrasi yang jujur perlu kita lakukan di sini: container bawaan tetap jauh lebih terkurung daripada proses biasa di host. Proses host biasa berjalan dengan capabilities penuh milik user-nya, tanpa filter seccomp tambahan, tanpa profil LSM khusus, dan tanpa kuota cgroups. Container bawaan sudah kehilangan sebagian besar capability root, sudah disaring seccomp, sudah dibatasi cgroups, dan pada banyak host sudah mengenakan profil LSM — semuanya tanpa satu pun flag tambahan dari kita. Section ini tidak menuntut kepanikan; section ini menuntut kesengajaan. Panik membuat tim menolak container sama sekali, sementara kelonggaran membuat tim menjalankan container dengan kebiasaan mesin virtual. Keduanya sama-sama salah; jalan yang benar adalah mengenali model ancaman lalu menegakkan least privilege lapis demi lapis.
Lapisan pertama yang akan kita kencangkan adalah lapis yang paling murah, paling tua, dan paling sering dilupakan sekaligus: identitas. Sejak chapter pertama course ini, hampir semua container kita berjalan sebagai root — kebiasaan warisan sebagian besar Dockerfile di dunia. Chapter Menjalankan Container Non-Root membedah rantai risikonya, pola penurunan identitas di Dockerfile maupun saat runtime, serta jebakan volume dan port yang menyertainya.
Referensi #
- Docker security — peta resmi seluruh mekanisme isolasi container dari namespace sampai LSM.
- Docker overview — arsitektur Docker dan hubungan container-kernel-host yang dibagi.
- Docker concepts — konsep container sebagai proses terisolasi di atas kernel bersama.