Container telah menjadi fondasi standar untuk deployment aplikasi modern. Namun, banyak developer yang menggunakan Docker atau Podman tanpa benar-benar memahami mekanisme internal yang memungkinkan isolasi filesystem. Padahal, memahami cara kerja container dari tingkat sistem operasi adalah keterampilan fundamental yang membedakan engineer senior dari yang masih junior.
Pada tutorial ini, kita akan membangun container dari nol menggunakan hanya tool bawaan Linux: unshare, mount, dan pivot_root. Tanpa Docker, tanpa runtime magic. Tujuan akhirnya adalah memahami bagaimana mount namespace bekerja sebagai fondasi isolasi container, sambil melihat peran komplementer dari namespace lain seperti PID, cgroup, UTS, dan network.
Docker dan Kubernetes menyederhanakan penggunaan container secara drastis. Namun, abstraction yang mereka berikan seringkali menyembunyikan detail penting. Ketika terjadi masalah filesystem, permission, atau mount propagation, pemahaman tentang mekanisme underlying menjadi sangat berharga.
Dengan membangun container dari nol, kamu akan memahami secara langsung bahwa container pada dasarnya hanyalah proses Linux biasa yang diisolasi menggunakan namespace dan cgroup. Ilusi sebuah distro Linux lengkap di dalam container sebenarnya dibangun dari manipulasi mount table yang cermat. Ini adalah insight yang tidak bisa didapat hanya dengan membaca dokumentasi Docker.
Tutorial ini memerlukan akses ke mesin Linux dengan kernel yang mendukung namespaces. Distribusi apa pun akan berfungsi selama kamu memiliki akses root atau sudo. Berikut yang perlu disiapkan:
Linux host dengan kernel 5.x atau lebih baru
Akses root atau sudo privileges
Familiaritas dasar dengan shell scripting
Pemahaman konsep mount dan filesystem hierarchy
Pastikan tool unshare tersedia di sistem. Verifikasi dengan menjalankan:
unshare --version
Jika tidak tersedia, install package util-linux yang biasanya sudah ada di semua distribusi utama.
Mount namespace adalah fondasi isolasi filesystem di container. Namespace ini mengisolasi daftar mount point yang dilihat oleh proses di dalamnya. Untuk memahami ini, mari kita lakukan eksperimen sederhana.
Buka dua terminal. Di terminal pertama, masuk ke mount namespace baru:
sudo unshare --mount bash
Di terminal kedua, buat file di host filesystem:
echo "Hello from host" | sudo tee /opt/marker.txt
File ini akan terlihat di kedua namespace karena mount namespace baru masih memiliki view yang sama terhadap filesystem. Perbedaan baru muncul ketika kita membuat mount point baru. Dari terminal pertama, jalankan:
sudo mount --bind /tmp /mnt
Sekarang isi /mnt di terminal pertama akan menunjukkan file dari /tmp, sedangkan di terminal kedua /mnt tetap kosong. Inilah isolasi mount namespace: setiap namespace memiliki mount table sendiri.
Untuk membuat container yang realistis, kita perlu rootfs yang terpisah dari host. Rootfs ini bisa berupa direktori yang berisi minimal struktur Linux seperti /bin, /lib, /etc, dan /proc.
Buat direktori rootfs dan salin binary dasar:
mkdir -p /tmp/mycontainer/rootfs
sudo debootstrap minimal /tmp/mycontainer/rootfs
Jika debootstrap tidak tersedia, kamu bisa menggunakan container image yang sudah ada dan mengekstraknya:
docker export 2af0e18985bed2eaa99475d8dd9bfe6722a2c85c7e58de3e631375faaf48fe19 | tar -C /tmp/mycontainer/rootfs -xvf -
Setelah rootfs siap, buat direktori untuk mount point lama:
mkdir -p /tmp/mycontainer/rootfs/.old_root
Perintah pivot_root memindangkan root filesystem saat ini ke lokasi baru, dan menggantinya dengan direktori yang kita tentukan. Ini adalah mekanisme inti yang digunakan Docker untuk mengganti view filesystem proses container.
Masuk ke mount namespace baru, lalu jalankan pivot_root:
sudo unshare --mount bash
cd /tmp/mycontainer
sudo pivot_root rootfs rootfs/.old_root
Setelah pivot_root, proses kita sekarang melihat /tmp/mycontainer/rootfs sebagai root direktori /. Semua file host berada di /.old_root. Langkah selanjutnya adalah unmount direktori lama untuk benar-benar memisahkan diri dari host:
umount -l /.old_root
Flag -l melakukan lazy unmount, yang memastikan filesystem dilepaskan begitu tidak lagi digunakan.
Container yang berfungsi memerlukan pseudo-filesystem seperti /proc dan /dev. Tanpa procfs, banyak tool Linux seperti ps dan top tidak akan berfungsi.
Mount procfs di dalam container:
mount -t proc proc /proc
Untuk device nodes, kita bisa menggunakan bind mount dari host atau membuat devtmpfs:
mount -t devtmpfs devtmpfs /dev
Jika kamu tidak ingin mengekspos semua device host, alternatif yang lebih aman adalah membuat devpts dan mem-bind mount hanya device yang diperlukan seperti /dev/null, /dev/zero, dan /dev/random.
Setelah filesystem terisolasi, jalankan proses di dalam container. Karena kita hanya menggunakan mount namespace tanpa PID namespace, shell kita masih memiliki PID yang sama. Namun, view filesystem-nya sudah sepenuhnya terisolasi.
Jalankan shell baru di dalam container:
exec /bin/bash
Coba jalankan perintah seperti ls /, cat /etc/os-release, atau ps aux. Kamu akan melihat bahwa sistem terlihat seperti distro Linux mandiri, meskipun sebenarnya ini hanyalah proses biasa di host dengan mount namespace terpisah.
Untuk meningkatkan isolasi, tambahkan flag --pid, --uts, dan --network saat menjalankan unshare. Ini akan menciptakan container yang jauh lebih mirip dengan Docker.
Container pada dasarnya adalah ilusi yang dibangun dari beberapa fitur kernel Linux: mount namespace, pivot_root, dan pseudo-filesystem. Dengan memahami mekanisme ini, developer tidak hanya menjadi lebih baik dalam menggunakan Docker, tetapi juga mampu mendiagnosis masalah yang terjadi di production.
Langkah selanjutnya adalah mengeksplorasi namespace tambahan dan cgroup untuk membatasi resource. Tutorial lengkap tentang container networking dari nol tersedia di iximiuz Labs: Container Networking. Untuk eksperimen hands-on dengan playground interaktif, kunjungi iximiuz Labs: Container Filesystem.
Dapatkan feedback, users, dan eksposur dari komunitas kreator, developer, dan entrepreneur digital Indonesia.
Submit Produk → Pelajari Dulu