Container pada dasarnya bersifat ephemeral, semua data yang ditulis di writable layer-nya ikut lenyap begitu container tersebut dihapus. Sifat ini cocok untuk proses yang stateless, tapi jadi masalah besar untuk aplikasi yang menyimpan data penting, misalnya database yang datanya harus tetap ada meski container-nya diganti dengan image versi baru. Sysadmin/DevOps Engineer yang mengelola database atau service stateful di production wajib paham cara menyimpan data agar tidak hilang setiap kali container di-restart, di-update, atau bahkan dipindah ke host lain. Developer juga perlu memahami konsep ini supaya data hasil development, misalnya database lokal untuk testing, tidak perlu dibangun ulang dari nol setiap kali container dihapus. Bab ini membahas volume, mekanisme penyimpanan data resmi milik Docker yang dirancang untuk lepas dari siklus hidup container mana pun yang memakainya.
10.1 Konsep Volume
Volume adalah mekanisme penyimpanan data yang dikelola langsung oleh Docker, terpisah dari writable layer container, sehingga datanya tetap bertahan meski container yang memakainya dihapus. Docker menyimpan volume di lokasi khusus pada filesystem host, biasanya di bawah /var/lib/docker/volumes/ pada Linux, dan mengelola seluruh proses pembuatan, penyimpanan, serta pembersihannya lewat Docker Engine.
10.1.1 Mengapa Volume Dibutuhkan
Setiap container berjalan di atas writable layer miliknya sendiri, lapisan tipis yang dibangun di atas image read-only. Semua perubahan yang terjadi selama container berjalan, termasuk file yang ditulis aplikasi, tersimpan di layer ini. Masalahnya, writable layer terikat erat dengan siklus hidup container: begitu container dihapus lewat docker rm, seluruh isi writable layer-nya ikut lenyap tanpa bisa dikembalikan lagi.
Untuk aplikasi stateless seperti web server yang tidak menyimpan data penting di dalam container, sifat ephemeral ini bukan masalah. Tapi untuk database seperti PostgreSQL atau MySQL, kehilangan data setiap kali container di-update ke image versi baru jelas tidak bisa diterima. Volume hadir sebagai jawaban atas masalah ini: data yang ditulis ke dalam volume tetap tersimpan di disk host secara independen, sehingga container boleh dihapus dan dibuat ulang berkali-kali tanpa mengorbankan datanya.
10.1.2 Volume vs Bind Mount vs Writable Layer
Docker menyediakan tiga cara berbeda untuk menangani data pada container, dan penting untuk memahami di mana posisi volume di antara ketiganya sebelum masuk ke praktik. Bind mount menghubungkan langsung sebuah direktori atau file spesifik di host ke dalam container, sehingga path-nya bergantung penuh pada struktur filesystem host. Volume berbeda: Docker yang mengelola lokasi penyimpanannya sendiri, kita tidak perlu (dan sebaiknya tidak) mengetahui atau bergantung pada struktur direktori host secara langsung.
| Aspek | Volume | Bind Mount | Writable Layer Container |
|---|---|---|---|
| Dikelola oleh | Docker Engine | Struktur direktori host, manual | Docker, terikat container |
| Lokasi penyimpanan | Area khusus Docker di host | Path bebas di filesystem host | Bagian dari container itu sendiri |
| Bertahan setelah container dihapus | Ya | Ya (data tetap ada di host) | Tidak |
| Portabilitas antar host | Lebih mudah dikelola lewat volume driver | Bergantung struktur direktori host tujuan | Tidak relevan |
Secara umum, volume lebih direkomendasikan Docker untuk kebanyakan use case karena Docker sendiri yang mengelola siklus hidup dan lokasi penyimpanannya, sehingga lebih mudah dipindahkan, di-backup, atau dikelola lewat Docker CLI tanpa perlu tahu detail struktur direktori host. Bind mount tetap punya tempatnya sendiri, terutama saat kita justru butuh akses langsung ke path spesifik di host, misalnya memasukkan source code development ke dalam container secara real-time.
10.2 Named Volumes vs Anonymous Volumes
Volume di Docker terbagi menjadi dua jenis berdasarkan cara penamaannya: named volume yang diberi nama eksplisit oleh kita, dan anonymous volume yang namanya dibuat otomatis oleh Docker berupa string acak. Perbedaan ini kelihatan sepele, tapi berdampak besar pada kemudahan mengelola data dalam jangka panjang.
10.2.1 Membuat dan Memakai Named Volume
Named volume dibuat dengan nama yang kita tentukan sendiri, sehingga mudah dirujuk kembali kapan pun dibutuhkan, baik untuk dipasang ke container lain maupun untuk keperluan backup. Buat named volume secara eksplisit lewat docker volume create.
docker volume create data-dbPasang volume yang sudah dibuat ke sebuah container lewat opsi -v (atau --volume) pada docker run, dengan format nama-volume:path-di-container.
docker run -d --name demo-db -v data-db:/var/lib/postgresql/data postgres:16Named volume tidak harus dibuat lebih dulu secara manual. Kalau nama volume yang disebut di opsi -v belum ada, Docker otomatis membuatnya saat container dijalankan.
docker run -d --name demo-app -v app-cache:/root/.cache alpine sleep 3600Docker juga menyediakan opsi --mount sebagai alternatif -v dengan sintaks yang lebih eksplisit dan verbose, memakai pasangan key=value. Dokumentasi resmi Docker merekomendasikan --mount untuk skenario yang butuh kontrol lebih detail, misalnya saat mengatur volume driver, subdirektori di dalam volume, atau mount pada Docker Swarm service.
docker run -d --name demo-db2 --mount type=volume,src=data-db,dst=/var/lib/postgresql/data postgres:16Untuk named volume, baik -v maupun --mount sama-sama otomatis membuatkan volume kalau namanya belum terdaftar, jadi tidak ada perbedaan perilaku auto-create di antara keduanya khusus untuk volume. Untuk kebanyakan kasus sehari-hari, -v tetap cukup dan lebih ringkas ditulis; --mount lebih relevan dipakai di skenario production yang butuh presisi konfigurasi lebih tinggi.
Batasi akses tulis container ke volume kalau memang tidak dibutuhkan, dengan menambahkan sufiks :ro (read-only) di akhir opsi -v. Praktik ini relevan untuk container utility yang hanya perlu membaca isi volume, misalnya container yang sekadar memindai atau menyalin isi volume untuk keperluan audit, sehingga risiko perubahan data yang tidak disengaja bisa ditekan.
docker run --rm -v app-cache:/root/.cache:ro alpine ls -la /root/.cache10.2.2 Anonymous Volume dan Risikonya
Anonymous volume tercipta saat kita memasang volume ke sebuah path di container tanpa menyebutkan nama volume-nya, cukup dengan menuliskan path tujuan saja.
docker run -d --name demo-anon -v /data alpine sleep 3600Docker memberi nama acak berupa string hash panjang untuk volume ini. Cek nama acak yang dihasilkan lewat docker inspect.
docker inspect --format '{{json .Mounts}}' demo-anonAnonymous volume tetap bertahan meski container yang memakainya dihapus, persis seperti named volume, kecuali container tersebut dijalankan dengan opsi --rm sejak awal. Bedanya, karena namanya berupa string acak, anonymous volume jauh lebih sulit diidentifikasi dan dirujuk kembali di kemudian hari. Ini pitfall yang sering menjebak Developer: menjalankan banyak container testing dengan anonymous volume, lalu kebingungan volume mana yang masih berisi data penting saat hendak dibersihkan, karena semua namanya cuma deretan karakter acak yang tidak bermakna.
Docker tidak otomatis menggabungkan anonymous volume antar container. Setiap container yang dijalankan dengan opsi anonymous volume yang sama (misalnya -v /data tanpa nama) akan membuat volume anonim baru yang terpisah, bukan memakai ulang volume anonim milik container sebelumnya. Kalau butuh berbagi data antar container, gunakan named volume atau rujuk anonymous volume lewat ID acaknya secara eksplisit.
Di lapangan, praktik terbaiknya adalah selalu memakai named volume untuk data yang benar-benar perlu dipertahankan, dan menghindari anonymous volume kecuali memang untuk kebutuhan sementara yang datanya boleh sulit dilacak. Kalau instruksi VOLUME di Dockerfile base image (misalnya image resmi PostgreSQL atau MySQL) otomatis membuat anonymous volume setiap kali container dijalankan tanpa opsi -v eksplisit, override path tersebut dengan named volume secara manual supaya datanya tetap mudah dikenali dan dikelola.
10.3 Volume Management
Docker CLI menyediakan subperintah docker volume untuk mengelola seluruh siklus hidup volume, dari melihat daftar, memeriksa detail, sampai menghapusnya.
10.3.1 Melihat dan Memeriksa Volume
Lihat daftar seluruh volume yang ada di host lewat docker volume ls.
docker volume lsDRIVER VOLUME NAME
local data-db
local app-cache
local a1b2c3d4e5f6...Kolom pertama menampilkan driver yang dipakai volume tersebut; local adalah driver bawaan Docker yang menyimpan data langsung di disk host. Untuk memeriksa detail sebuah volume, termasuk lokasi penyimpanan fisiknya di host, gunakan docker volume inspect.
docker volume inspect data-db[
{
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/data-db/_data",
"Name": "data-db",
"Options": {},
"Scope": "local"
}
]Field Mountpoint menunjukkan lokasi sebenarnya data volume tersimpan di filesystem host. Meski secara teknis bisa diakses langsung lewat path ini, Docker tidak merekomendasikan mengubah isinya secara manual dari luar container karena berisiko membuat data tidak konsisten dengan yang dibaca container yang sedang memakainya.
10.3.2 Menghapus Volume
Hapus volume yang sudah tidak dipakai lewat docker volume rm. Volume hanya bisa dihapus kalau sudah tidak terhubung ke container mana pun, baik yang sedang berjalan maupun yang berstatus berhenti.
docker volume rm app-cacheKalau volume masih dipakai container, Docker menolak penghapusan dengan pesan error yang menyebutkan volume tersebut masih in use. Hapus atau lepaskan dulu container yang memakainya sebelum volume bisa dihapus.
Untuk membersihkan volume yang menumpuk tanpa terpakai, gunakan docker volume prune. Secara default, perintah ini hanya menghapus anonymous volume yang tidak terhubung ke container mana pun; named volume tetap aman meski tidak sedang dipakai container apa pun.
docker volume pruneWARNING! This will remove anonymous local volumes not used by at least one container.
Are you sure you want to continue? [y/N] yUntuk ikut menghapus named volume yang tidak terpakai, tambahkan opsi --all.
docker volume prune --allTrustworthiness soal perintah ini penting ditekankan: docker volume prune --all berpotensi menghapus data permanen kalau ada named volume berisi data penting yang kebetulan sedang tidak terhubung ke container mana pun, misalnya container yang memakainya sudah lebih dulu dihapus tanpa sengaja. Volume memang sengaja tidak pernah dihapus otomatis oleh Docker justru untuk mencegah risiko kehilangan data semacam ini. Sebelum menjalankan perintah ini di server production, selalu periksa dulu daftar volume lewat docker volume ls dan pastikan tidak ada data penting yang masih dibutuhkan.
10.4 Volume Drivers
Volume driver menentukan bagaimana dan di mana data volume sebenarnya disimpan. Driver bawaan Docker adalah local, yang menyimpan data langsung di disk host tempat Docker Engine berjalan. Untuk kebutuhan yang lebih kompleks, misalnya menyimpan data di sistem penyimpanan jaringan atau cloud storage, volume driver pihak ketiga bisa dipasang sebagai plugin.
10.4.1 Driver Local dan Opsinya
Secara default, docker volume create memakai driver local tanpa perlu disebutkan secara eksplisit. Driver ini bisa menerima opsi mount tambahan lewat flag --opt, misalnya untuk memasang direktori NFS sebagai sumber data volume.
docker volume create --driver local \
--opt type=nfs \
--opt o=addr=192.168.1.100,rw \
--opt device=:/path/to/share \
data-nfsKonfigurasi ini berguna buat Sysadmin/DevOps Engineer yang mengelola beberapa Docker host dan ingin memastikan data volume tetap bisa diakses meski container dipindah ke host lain, karena data sebenarnya tersimpan di storage jaringan terpisah, bukan disk lokal masing-masing host.
10.4.2 Volume Driver Plugin Pihak Ketiga
Selain driver local bawaan, Docker mendukung ekosistem plugin volume driver pihak ketiga yang memperluas kemampuan penyimpanan volume ke berbagai backend storage, misalnya cloud object storage atau distributed filesystem. Pasang volume dengan plugin driver tertentu lewat opsi --driver saat membuat volume.
docker volume create --driver=nama-plugin nama-volume
docker run -it --volume nama-volume:/data alpine shSebelum memasang plugin volume driver pihak ketiga di production, verifikasi dulu sumber dan reputasi plugin tersebut, karena plugin volume berjalan dengan akses langsung ke data container dan berpotensi jadi celah keamanan kalau berasal dari sumber yang tidak tepercaya. Untuk kebanyakan kebutuhan development sehari-hari, driver local bawaan sudah cukup memadai tanpa perlu plugin tambahan.
10.5 Sharing Data Antar Container
Salah satu kegunaan utama volume adalah berbagi data antar beberapa container sekaligus, misalnya container aplikasi yang menulis file log dan container terpisah yang membaca log tersebut untuk diproses lebih lanjut.
10.5.1 Memasang Volume yang Sama ke Beberapa Container
Cara paling langsung berbagi data adalah memasang named volume yang sama ke beberapa container sekaligus lewat opsi -v.
docker volume create shared-logs
docker run -d --name app-writer -v shared-logs:/var/log/app alpine sh -c "while true; do date >> /var/log/app/app.log; sleep 5; done"
docker run -d --name app-reader -v shared-logs:/var/log/app alpine sh -c "tail -f /var/log/app/app.log"Kedua container di atas mengakses direktori data yang sama persis lewat volume shared-logs, meski path mount di masing-masing container bisa saja berbeda kalau memang dibutuhkan. Verifikasi data yang tertulis benar-benar terbaca oleh container kedua lewat docker logs.
docker logs app-reader10.5.2 Volumes-From untuk Mewarisi Konfigurasi Mount
Opsi --volumes-from menyalin seluruh konfigurasi mount volume dari container lain, berguna saat kita ingin sebuah container mewarisi persis volume yang sama dengan container acuan tanpa perlu menuliskan ulang setiap detail mount-nya satu per satu.
docker run -d --name data-holder -v shared-data:/data alpine sleep 3600
docker run --rm --volumes-from data-holder alpine ls /dataPola ini umum dipakai untuk container utility sekali pakai, misalnya container backup yang perlu mengakses volume milik container database tanpa harus tahu detail nama volume aslinya, cukup merujuk nama container yang sudah memasangnya.
docker run --rm --volumes-from demo-db -v $(pwd)/backup:/backup alpine tar czf /backup/db-backup.tar.gz /var/lib/postgresql/dataDi lapangan, berbagi volume antar container lewat pola ini sangat membantu untuk skenario sidecar, misalnya container utama yang menjalankan aplikasi dan container terpisah yang bertugas memonitor atau memproses data yang sama tanpa perlu duplikasi storage. Perlu diperhatikan, kalau lebih dari satu container menulis ke volume yang sama secara bersamaan tanpa mekanisme locking yang tepat, risiko race condition pada data tetap ada; volume sendiri tidak menyediakan mekanisme locking otomatis, jadi tanggung jawab menjaga konsistensi data tetap ada di sisi aplikasi.
Bersihkan seluruh container dan volume contoh yang sudah dipakai sepanjang bab ini, supaya tidak ada sisa data testing yang menumpuk di mesin kita.
docker rm -fv demo-db demo-app demo-anon demo-db2 app-writer app-reader data-holder
docker volume rm data-db app-cache shared-logs shared-data data-nfsOpsi -v pada docker rm ikut menghapus anonymous volume yang terhubung ke container yang dihapus, seperti volume anonim milik demo-anon. Named volume seperti data-db dan app-cache tetap harus dihapus terpisah lewat docker volume rm karena, seperti dibahas di sub-bab pengelolaan volume, opsi -v tersebut tidak berlaku untuk named volume.
| Perintah | Fungsi |
|---|---|
docker volume create <nama> | Membuat named volume baru |
docker run -v <nama>:<path> image | Memasang volume ke path tertentu di container |
docker volume ls | Menampilkan daftar seluruh volume |
docker volume inspect <nama> | Melihat detail dan lokasi penyimpanan volume |
docker volume rm <nama> | Menghapus volume yang tidak lagi dipakai container mana pun |
docker volume prune --all | Menghapus seluruh volume (termasuk named volume) yang tidak terpakai |
docker run --volumes-from <container> | Mewarisi seluruh konfigurasi mount volume dari container lain |

