Kita baru saja menutup Chapter Tmpfs Mount dengan tiga jenis mount yang seluruhnya sudah pernah kita pegang: volume data-web yang menyimpan halo.txt, bind mount yang menjembatani direktori /home/budi/situs ke dalam container, dan tmpfs yang isinya lenyap begitu container berhenti. Penutup chapter itu menitipkan satu janji: kerangka memilih akan diuji dengan skenario demi skenario, termasuk kasus yang memakai ketiga jenis mount sekaligus dalam satu deployment. Pertanyaannya kini bergeser dari “bagaimana cara memakainya” menjadi “mana yang harus dipilih” — dan ini bukan pertanyaan akademik, karena pilihan yang salah langsung terasa di dunia nyata: data database yang hilang bersama container yang dihapus, alur edit-uji yang tersendat karena source code tersalin ke dalam image, atau secret yang tercecer di disk padahal seharusnya hanya hidup di memori. Chapter ini menyusun kerangka keputusannya — tabel delapan dimensi, alur tiga pertanyaan, dan tiga skenario nyata — supaya kita bisa memilih dalam hitungan detik, bukan dengan menebak-nebak; janji tentang deployment yang memakai ketiga jenis mount sekaligus itu sendiri akan kita tepati pada Chapter Mount Read-Only.

Tiga Jenis Mount dalam Satu Tabel #

Ketiga jenis mount terasa mirip karena semuanya menampilkan berkas di dalam container, tetapi mekanisme di baliknya berbeda total. Tabel berikut membandingkan ketiganya dari delapan dimensi yang paling sering menentukan keputusan di lapangan:

DimensiVolumeBind MountTmpfs Mount
Lokasi fisik dataArea khusus Docker di disk host, misalnya /var/lib/docker/volumes/<nama>/_dataPath apa pun di host yang kita tunjuk sendiriRAM host, tidak pernah menulis ke disk
Dikelola olehDocker daemon sepenuhnya, dari pembuatan sampai penghapusanKita sendiri, Docker hanya menjembatani path yang kita pilihKernel Linux lewat filesystem tmpfs
Portabilitas lintas hostTinggi — data berpindah lewat pola backup-restore tanpa peduli struktur direktori hostRendah — host baru harus menyiapkan struktur path yang sama persisTidak relevan — data memang tidak dirancang berpindah
Kemudahan backupMudah — pola helper container resmi mengarsipkan isi volumeMudah — berkasnya berkas host biasa untuk tool backup apa punTidak perlu dibackup — isi hilang saat container berhenti
Kinerja tulis beratBaik — penulisan langsung ke filesystem host tanpa lapisan tambahanBaik di Linux; melambat di Docker Desktop karena menembus lapisan berbagi berkas VMSangat cepat karena di RAM, tetapi memakan memori dan batas ukurannya kecil
Persisten setelah docker rmYa — volume tetap berdiri sampai docker volume rmYa — berkas memang milik host sejak awalTidak — hilang begitu container berhenti
Use case idealDatabase, state aplikasi, data yang dibagi antar containerKonfigurasi produksi, source code saat pengembangan, berkas referensiSecret sementara, cache antar-langkah, data sensitif sekali pakai
Dukungan platformLinux, macOS, WindowsLinux, macOS, WindowsHanya kernel Linux; Docker Desktop menyediakannya lewat VM Linux-nya

Mari kita telaah dimensi-dimensi yang paling sering menentukan keputusan:

  1. Kolom “dikelola oleh” adalah akar dari hampir semua perbedaan lain. Volume hidup di wilayah yang dikuasai Docker, sehingga Docker pula yang menjamin pola pendataan, backup, dan pembersihannya; bind mount hidup di wilayah kita, sehingga Docker tidak tahu apa-apa tentang isi path itu dan hanya menyediakan jembatan.
  2. Kolom “portabilitas lintas host” menentukan nasib aplikasi saat pindah server. Volume bisa dibungkus menjadi arsip dan dituangkan kembali di host mana pun; bind mount mengikat kita pada struktur direktori host — path /home/budi/situs tidak berarti apa pun di host baru dengan nama user berbeda.
  3. Kolom “kinerja tulis berat” sering diabaikan sampai database berat mulai tersendat. Di Linux, volume dan bind mount sama-sama menulis langsung ke filesystem host; di macOS dan Windows, bind mount harus menembus lapisan berbagi berkas antara host dan VM Linux di dalam Docker Desktop, dan penulisan berkas kecil yang sangat sering adalah pola paling menderita dalam skenario itu.
  4. Kolom “persisten setelah docker rm” mengingatkan pelajaran Chapter Konsep Persistence: yang menentukan umur data bukan container, melainkan jenis mount yang menampungnya — hanya volume dan bind yang sanggup melampaui docker rm, sementara tmpfs sengaja dibuat sebaliknya.

Alur Keputusan #

Delapan dimensi di atas tersaring menjadi tiga pertanyaan berurutan yang bisa kita lalui dalam hitungan detik. Diagram berikut memetakan alurnya:

Diagram tanpa penjelasan hanya setengah keputusan, jadi mari kita telaah empat langkahnya satu per satu:

  1. Langkah pertama — tanya umur data. Bila data harus bertahan melewati docker rm — database, unggahan pengguna, log penting — kita masuk cabang kiri; bila tidak, cabang kanan menunggu. Pertanyaan ini adalah versi ringkas dari seluruh Chapter Konsep Persistence.
  2. Langkah kedua — tanya siapa pemilik sah berkasnya. Data yang harus bertahan masih terbelah dua: berkas yang memang sudah hidup dan diedit di host (source code yang kita utak-atik di editor, konfigurasi yang dikelola tool host) jatuh ke bind mount; data yang lahir dari aplikasi di dalam container dan tidak punya alasan hidup di path host tertentu jatuh ke volume.
  3. Langkah ketiga — tanya sifat datanya. Data yang tidak perlu bertahan dan bersifat sementara atau sensitif — token sekali pakai, hasil antar-langkah, berkas yang tidak boleh menyentuh disk — adalah wilayah tmpfs; setelah container berhenti, tidak ada jejak yang perlu dibersihkan.
  4. Langkah keempat — jatuh ke writable layer. Bila semua pertanyaan terjawab “tidak”, data memang boleh hidup dan mati bersama container di writable layer yang kita bedah pada Chapter Writable Container Layer; ini bukan pilihan buruk, melainkan pilihan tepat untuk data yang benar-benar sekali pakai.

Hasil alur tersebut diringkas menjadi tabel keputusan sehari-hari berikut:

SituasiPilihanAlasan ringkas
Data penting, lahir dari aplikasi containerVolumePersisten, dikelola Docker, mudah dibackup dan dipindah
Source code atau konfigurasi yang diedit di hostBind mountPerubahan host langsung terlihat container tanpa menyalin ulang
Data sementara atau sensitif sekali pakaiTmpfs mountHidup di RAM, tidak menyentuh disk, lenyap saat berhenti
Data sekali pakai yang tidak sensitifWritable layerIkut umur container, tanpa biaya pengelolaan

Rekomendasi Resmi #

Dokumentasi Docker sendiri tidak membiarkan kita mengarang aturan sendiri: gunakan volume untuk data persisten pada umumnya, gunakan bind mount untuk berbagi konfigurasi atau source code dari host ke container — terutama saat pengembangan — dan gunakan tmpfs untuk data sementara yang tidak boleh bertahan, termasuk data sensitif. Rekomendasi ini bukan selera, melainkan konsekuensi dari tabel delapan dimensi di atas: volume menang pada portabilitas, backup, dan kinerja tulis untuk data aplikasi, sementara bind mount menang justru pada dimensi yang tidak dimiliki volume — berbagi berkas yang sudah ada dan sedang diedit di host.

Tiga Skenario Nyata #

Tabel dan diagram baru benar-benar melekat setelah kita melihatnya bekerja. Tiga skenario berikut memakai ketiga jenis mount dalam keadaan yang paling sering kita temui di pekerjaan nyata.

Skenario 1 — Database Produksi dengan Volume #

Skenario pertama adalah keputusan yang paling mahal apabila salah: database produksi. Budi menaikkan PostgreSQL untuk aplikasi internal kantornya, dan datanya wajib bertahan melewati apa pun yang terjadi pada container — patch image, restart, bahkan penghapusan. Volume pgdata peninggalan Chapter Volume masih setia menunggu, jadi keputusan memilih volume tinggal dieksekusi:

bash
$ docker run -d --name db \
    -e POSTGRES_PASSWORD=rahasia123 \
    -v pgdata:/var/lib/postgresql/data \
    postgres:18-alpine

Output yang Dihasilkan:

text
678d6406c1dc061313cd0e9770c8024a48f5f4df06b476233a45b8e93228e1ee

Setelah database siap — hanya beberapa detik karena direktori datanya sudah terisi — Budi membuktikan bahwa engine hidup dan volumenya tercatat:

bash
$ docker exec db pg_isready -U postgres

Output yang Dihasilkan:

text
/var/run/postgresql:5432 - accepting connections
bash
$ docker volume ls

Output yang Dihasilkan:

text
DRIVER    VOLUME NAME
local     data-web
local     latihan-volume
local     pgdata

data-web dan latihan-volume adalah kenalan dari chapter-chapter sebelumnya. Sekarang ujian yang paling meyakinkan justru tidak membutuhkan ritual apa pun — kita intip isi database-nya langsung:

bash
$ docker exec db psql -U postgres -c "\dt"

Output yang Dihasilkan:

text
         List of relations
 Schema |   Name   | Type  |  Owner
--------+----------+-------+----------
 public | peserta  | table | postgres
(1 row)

Mari kita telaah rangkaian bukti di atas:

  1. -v pgdata:/var/lib/postgresql/data — volume bernama dipasang tepat di direktori data image postgres, sehingga seluruh penulisan engine mendarat di volume, bukan di writable layer.
  2. Output langsung ID tanpa baris pull — image postgres:18-alpine sudah lokal sejak Chapter Volume; inisialisasi ulang juga dilewati karena direktori data di volume sudah terisi, itulah sebabnya container siap dalam hitungan detik.
  3. \dt menemukan tabel peserta — tabel itu lahir pada Chapter Volume di tangan container db-latihan yang sudah lama dihapus; datanya terus hidup di pgdata dan langsung dikenali container baru ini tanpa satu langkah pemulihan. Persistensi yang dulu kita buktikan lewat ritual hapus-lalu-jalankan-ulang kini bekerja begitu saja.
  4. Pilihan volume di sini sekaligus pintu perawatan data — volume bernama mudah dirujuk di docker volume ls, mudah diaudit, dan mudah dibekukan menjadi arsip cadangan lewat pola helper container pada Chapter Backup dan Restore Volume.

Skenario 2 — Situs Dev dengan Bind Mount Read-Only #

Skenario kedua adalah keseharian pengembangan: situs statis yang sedang dipoles di editor. Direktori /home/budi/situs — bekas arena latihan Chapter Bind Mount yang halamannya terakhir berisi versi 2 — masih setia menunggu di host, dan berkas-berkasnya memang sudah hidup serta terus diedit dari host, sehingga bind mount adalah pilihan alurnya. Karena container nginx kali ini hanya perlu membaca, Budi menambahkan suffix :ro yang akan kita bedah tuntas pada Chapter Mount Read-Only:

bash
$ docker run -d --name web-dev \
    -p 8081:80 \
    -v /home/budi/situs:/usr/share/nginx/html:ro \
    nginx:1.29-alpine

Output yang Dihasilkan:

text
Unable to find image 'nginx:1.29-alpine' locally
1.29-alpine: Pulling from library/nginx
...
Digest: sha256:4f2c9d8e7a1b...
Status: Downloaded newer image for nginx:1.29-alpine
f2b3d0fa9374ef3efb78330c3094cef358dcdd395bfeb66837c6e6343d3088d5

Keunggulan khas bind mount ini sudah kita saksikan pada Chapter Bind Mount — perubahan di host terlihat seketika tanpa membangun ulang apa pun — dan kali ini kita menikmatinya dengan container yang terkunci:

bash
$ curl localhost:8081

Output yang Dihasilkan:

text
<h1>versi 2</h1>
bash
$ echo '<h1>versi 3</h1>' > /home/budi/situs/index.html
$ curl localhost:8081

Output yang Dihasilkan:

text
<h1>versi 3</h1>

Mari kita telaah mengapa alur ini layak mendapat bind mount:

  1. -v /home/budi/situs:/usr/share/nginx/html:ro — direktori host dijembatani ke akar dokumen nginx; setiap penyimpanan di editor langsung menjadi isi situs, tanpa docker build dan tanpa pembuatan container ulang.
  2. curl pertama menyambut versi 2 — halaman itu adalah warisan utuh dari latihan Chapter Bind Mount; bind mount memang membawa berkas apa adanya, bukan salinan segar.
  3. Suffix :ro menjaga arah aliran — satu arah dari host ke container: editor kita menulis, nginx hanya membaca, sehingga proses di dalam container tidak akan pernah merusak source yang sedang dipoles; detail perilakunya kita bedah tuntas pada Chapter Mount Read-Only.

Skenario 3 — API Key untuk Batch Job dengan Tmpfs #

Skenario ketiga milik pekerjaan tengah malam: batch job yang membutuhkan API key untuk membaca layanan eksternal. Kredensial tidak boleh menetap di disk — tidak di image, tidak di writable layer — sehingga tmpfs adalah satu-satunya kandidat, dengan mode direktori yang dikunci untuk pemiliknya saja:

bash
$ docker run --rm \
    --mount type=tmpfs,destination=/run/secret,tmpfs-mode=1700 \
    -e API_KEY=rahasia123 \
    alpine:3.20 \
    sh -c 'umask 077; printf "%s" "$API_KEY" > /run/secret/api.key && ls -l /run/secret && cat /run/secret/api.key'

Output yang Dihasilkan:

text
total 4
-rw-------    1 root     root            10 Oct 13 15:18 api.key
rahasia123

Kita periksa juga mode direktorinya sendiri:

bash
$ docker run --rm \
    --mount type=tmpfs,destination=/run/secret,tmpfs-mode=1700 \
    alpine:3.20 ls -ld /run/secret

Output yang Dihasilkan:

text
drwx------T 2 root root 40 Oct 13 15:19 /run/secret

Mari kita telaah kedua hasil di atas:

  1. tmpfs-mode=1700 — angka 7 memberi rwx kepada pemilik direktori, dua angka 0 menghapus seluruh hak grup dan pihak lain, sementara angka 1 di depan memasang sticky bit: berkas di dalamnya hanya bisa dihapus pemiliknya, pola yang sama dengan /tmp sistem Linux pada umumnya.
  2. -e API_KEY=rahasia123 — kredensial masuk lewat environment variable, lalu dituangkan ke berkas di tmpfs dengan umask 077 sehingga berkasnya terkunci mode 600; aplikasi batch tinggal membaca /run/secret/api.key seperti membaca berkas biasa.
  3. --rm menutup kisahnya sendiri — begitu batch job selesai, container dihapus, tmpfs ikut terlepas dari memori, dan tidak ada jejak rahasia123 di disk mana pun; inilah sifat yang membuat tmpfs pantas menyimpan data sensitif sekali pakai.
  4. Bentuk --mount — skenario ini sengaja memakai bentuk panjang --mount type=tmpfs,... karena opsi tmpfs-mode hanya tersedia di sana; hasil yang sama sebenarnya bisa dicapai lewat flag --tmpfs, materi yang sudah kita bahas pada Chapter Tmpfs Mount.

Sebelum melangkah, kita rapikan mesin latihan agar bab-bab berikutnya mulai dari keadaan yang terkendali. Container db dan web-dev sudah menuntaskan tugas peragaannya:

bash
$ docker rm -f db web-dev

Output yang Dihasilkan:

text
db
web-dev

Volume pgdata, volume data-web, dan direktori /home/budi/situs sengaja kita biarkan — volume produksi memang tidak dibuang hanya karena latihan selesai, dan ketiganya masih menjadi bahan cerita pada chapter-chapter berikutnya. Volume memang begitu: sekali dipilih untuk data penting, ia setia menunggu sampai diminta lagi.

Dari tiga skenario tadi terlihat satu pola yang belum kita kunci: hampir semua mount yang kita pasang masih terbuka untuk ditulis oleh container — suffix :ro pada skenario situs baru selangkah menjadi kebiasaan. Bagaimana jika kita ingin melindungi data dari container itu sendiri, menjadikannya benar-benar hanya-baca bagi proses di dalamnya, bahkan mengunci seluruh akar filesystem container? Itu pekerjaan suffix :ro dan flag --read-only, materi Chapter Mount Read-Only.

Referensi #

  • Storage di Docker Engine — halaman induk konsep penyimpanan dan peta tiga jenis mount.
  • Volumes — rekomendasi resmi volume untuk data persisten.
  • Bind Mounts — panduan bind mount untuk konfigurasi dan source code.
  • Tmpfs Mounts — panduan tmpfs untuk data sementara dan sensitif.