Bind Mount

Bind Mount

Bitnesia Sep 12, 2026 10 EN

Saat sedang membangun aplikasi, Developer sering ingin perubahan source code langsung terlihat di dalam container tanpa harus build ulang image setiap kali menyimpan file. Di sisi lain, Sysadmin/DevOps Engineer kadang perlu memasukkan file konfigurasi spesifik dari host, misalnya sertifikat TLS atau file konfigurasi nginx.conf, ke dalam container tanpa membungkusnya ke image. Kedua kebutuhan ini punya jawaban yang sama: bind mount, mekanisme yang menghubungkan langsung sebuah path di filesystem host ke path tertentu di dalam container. Bab ini membahas cara kerja bind mount, bagaimana bedanya dengan volume, praktik pemakaiannya, sampai masalah permission yang paling sering muncul di lapangan.

11.1 Perbedaan Volume dan Bind Mount

Bind mount adalah mekanisme mount yang menghubungkan sebuah file atau direktori spesifik di filesystem host langsung ke path tertentu di dalam container, memakai path absolut milik host apa adanya. Berbeda dengan volume yang lokasi penyimpanannya dikelola sepenuhnya oleh Docker Engine, bind mount bergantung penuh pada struktur direktori host tempat Docker dijalankan.

11.1.1 Cara Kerja Bind Mount

Saat sebuah bind mount dipasang, Docker tidak menyalin data apa pun. Container hanya diberi akses langsung ke path host yang sama persis, sehingga perubahan yang terjadi di salah satu sisi (baik dari dalam container maupun dari host) langsung terlihat di sisi lainnya secara real-time. Sifat ini berbeda dari volume, yang meski juga bertahan di luar siklus hidup container, lokasi fisiknya berada di area khusus yang dikelola Docker dan tidak dimaksudkan untuk diakses manual dari host.

Konsekuensi dari cara kerja ini adalah bind mount sangat bergantung pada struktur filesystem host tempat ia dijalankan. Sebuah docker run yang memakai bind mount ke path /home/user/project hanya akan berjalan benar di mesin yang memang punya direktori tersebut; pindah ke host lain dengan struktur direktori berbeda, perintah yang sama bisa gagal atau salah mount.

11.1.2 Kapan Memilih Bind Mount, Kapan Memilih Volume

Pemilihan antara volume dan bind mount bergantung pada siapa yang perlu mengelola datanya. Kalau Docker yang harus mengelola penyimpanan data secara mandiri dan portabel, misalnya data database di production, volume adalah pilihan yang lebih tepat. Kalau kita justru butuh akses langsung dan dua arah ke path spesifik di host, misalnya memasukkan source code development ke container secara real-time, bind mount adalah jawabannya.

AspekVolumeBind Mount
Lokasi penyimpananDikelola Docker, area khusus di hostPath bebas, ditentukan manual di host
Portabilitas antar hostLebih mudah, tidak bergantung struktur direktori hostBergantung penuh pada struktur direktori host tujuan
Akses langsung dari hostTidak direkomendasikan, sebaiknya lewat containerBebas diakses dan diedit langsung dari host
Dukungan volume driverYa (local, NFS, plugin pihak ketiga)Tidak, hanya filesystem host apa adanya
Use case umumData persisten aplikasi/database di productionLive reload development, mount file konfigurasi

Di lapangan, kombinasi keduanya justru lazim dipakai dalam satu docker-compose.yml yang sama: bind mount untuk source code aplikasi yang sedang dikembangkan, dan named volume untuk data database yang harus tetap persisten dan portabel.

11.2 Menggunakan Bind Mount

Docker menyediakan dua cara memasang bind mount lewat docker run: opsi -v (atau --volume) yang ringkas, dan opsi --mount yang lebih eksplisit. Kedua opsi ini menghasilkan mount yang secara fungsional sama, tapi punya sedikit perbedaan perilaku yang penting dipahami.

11.2.1 Sintaks -v untuk Bind Mount

Pasang bind mount lewat opsi -v dengan format path-host:path-container. Path di sisi host wajib berupa path absolut; kalau path yang ditulis bukan path absolut dan bukan nama volume yang valid, Docker akan menganggapnya sebagai nama named volume, bukan bind mount.

docker run -d --name demo-nginx -v /home/user/website:/usr/share/nginx/html nginx:alpine

Perintah di atas memasang direktori /home/user/website milik host ke path /usr/share/nginx/html di dalam container. Untuk path relatif terhadap direktori kerja saat ini, gunakan $(pwd) pada Linux/macOS atau variabel setara di shell Windows supaya path tetap terselesaikan sebagai path absolut.

docker run -d --name demo-app -v $(pwd)/src:/app/src node:20-alpine

Kalau path host yang disebut di opsi -v belum ada di filesystem, Docker otomatis membuatkannya sebagai direktori kosong sebelum container dijalankan. Perilaku auto-create ini kadang jadi jebakan tersendiri: salah ketik nama direktori source code bisa membuat Docker diam-diam membuat direktori baru yang kosong alih-alih memunculkan error, sehingga container berjalan tanpa file yang seharusnya ada.

11.2.2 Sintaks --mount untuk Bind Mount

Opsi --mount memakai pasangan key=value yang lebih verbose namun lebih jelas maksudnya, dengan type=bind untuk menandakan jenis mount-nya.

docker run -d --name demo-nginx2 --mount type=bind,source=/home/user/website,target=/usr/share/nginx/html nginx:alpine

Perbedaan penting antara -v dan --mount untuk bind mount ada pada penanganan path host yang belum ada. Berbeda dengan -v yang otomatis membuat direktori baru, --mount akan menghasilkan error dan menolak menjalankan container kalau path sumber di host belum ada. Perilaku --mount ini lebih aman untuk mencegah kesalahan ketik path berubah jadi mount ke direktori kosong yang tidak disengaja, sehingga dokumentasi resmi Docker merekomendasikan --mount untuk skenario yang butuh kepastian dan presisi konfigurasi, terutama di production.

11.2.3 Bind Mount Read-Only

Batasi akses tulis container ke bind mount kalau container memang hanya perlu membaca isinya, misalnya saat memasukkan file konfigurasi yang tidak boleh diubah dari dalam container. Tambahkan sufiks :ro di akhir opsi -v, atau opsi readonly pada --mount.

docker run -d --name demo-conf -v /etc/app/config.yaml:/app/config.yaml:ro alpine:latest sleep 3600
docker run -d --name demo-conf2 --mount type=bind,source=/etc/app/config.yaml,target=/app/config.yaml,readonly alpine:latest sleep 3600

Verifikasi mount sudah benar-benar read-only lewat percobaan menulis dari dalam container; Docker akan menolak operasi tulis dengan pesan error filesystem read-only.

docker exec demo-conf sh -c "echo test >> /app/config.yaml"
sh: can't create /app/config.yaml: Read-only file system

11.3 Use Case Bind Mount

Bind mount paling sering dipakai di dua skenario utama: mempercepat workflow development lewat live reload, dan memasukkan file konfigurasi atau resource spesifik host ke dalam container tanpa membangunnya ke image.

11.3.1 Live Reload untuk Development

Developer yang sedang membangun aplikasi umumnya tidak ingin build image ulang setiap kali mengubah satu baris kode. Dengan bind mount, source code di host langsung terhubung ke direktori kerja aplikasi di dalam container, sehingga perubahan file di editor langsung terbaca oleh proses yang berjalan di container, asal aplikasi memang punya mekanisme reload otomatis seperti nodemon untuk Node.js atau flag --reload pada Uvicorn.

docker run -d --name dev-app -p 3000:3000 -v $(pwd):/app -w /app node:20-alpine sh -c "npm install && npm run dev"

Pola ini juga jamak dipakai lewat docker-compose.yml, di mana bind mount didefinisikan lewat key volumes pada service yang sedang dikembangkan.

services:
  app:
    image: node:20-alpine
    working_dir: /app
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    command: sh -c "npm install && npm run dev"

Di lapangan, praktik ini hanya relevan untuk environment development. Bind mount source code langsung dari host ke container jangan dipakai di production, karena image production seharusnya sudah membawa source code final di dalamnya, bukan bergantung pada struktur direktori host yang menjalankannya.

11.3.2 Mount File Konfigurasi dan Resource Host

Skenario umum lain di lingkungan production adalah memasukkan file konfigurasi, sertifikat TLS, atau resource lain milik host langsung ke container tanpa membungkusnya ke image, sehingga file sensitif seperti sertifikat tidak ikut tersimpan permanen di image yang bisa didistribusikan ke registry.

docker run -d --name web-tls -p 443:443 \
  -v /etc/ssl/certs/mysite.crt:/etc/nginx/ssl/mysite.crt:ro \
  -v /etc/ssl/private/mysite.key:/etc/nginx/ssl/mysite.key:ro \
  nginx:alpine

Sysadmin/DevOps Engineer juga sering memakai bind mount untuk mengakses socket milik host dari dalam container, contoh paling umum adalah mount /var/run/docker.sock supaya sebuah container bisa berkomunikasi dengan Docker Engine di host-nya sendiri, misalnya dipakai tool monitoring container seperti Portainer.

docker run -d --name portainer -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer-ce:latest

Trustworthiness penting ditekankan di sini: memberi container akses ke docker.sock milik host secara efektif memberi container tersebut kontrol penuh atas Docker Engine, setara akses root di host. Kalau image yang dipakai berasal dari sumber tidak tepercaya atau punya vulnerability, attacker yang berhasil mengeksploitasi container tersebut bisa memakai akses ke docker.sock untuk membuat container baru dengan hak akses penuh ke seluruh filesystem host. Mount docker.sock hanya ke image yang benar-benar tepercaya dan sudah diverifikasi sumbernya.

11.4 Permissions dan Troubleshooting

Bind mount adalah salah satu sumber masalah paling sering ditemui Developer maupun Sysadmin/DevOps Engineer di lapangan, terutama soal permission file dan perbedaan perilaku antar sistem operasi host.

11.4.1 Masalah Permission UID/GID

Bind mount tidak mengubah kepemilikan file sama sekali; permission dan owner file yang terlihat dari dalam container persis sama dengan yang tersimpan di host, ditentukan oleh UID dan GID numerik, bukan nama user. Masalah paling umum muncul saat proses di dalam container berjalan dengan UID yang berbeda dari owner file di host, misalnya container menjalankan aplikasi sebagai user non-root dengan UID 1000 sementara file di host dimiliki oleh UID root (0). Akibatnya, proses di dalam container gagal membaca atau menulis file tersebut meski secara kasat mata permission-nya terlihat wajar dari sisi host.

docker exec demo-app whoami
docker exec demo-app id

Samakan UID proses di dalam container dengan owner file di host lewat opsi --user saat menjalankan container, memakai format UID:GID.

docker run -d --name demo-app2 --user 1000:1000 -v $(pwd):/app node:20-alpine sh -c "npm run dev"

Alternatif lain, sesuaikan owner direktori di host supaya cocok dengan UID default yang dipakai proses di dalam image, lewat chown di sisi host sebelum container dijalankan. Cara ini lebih umum dipakai kalau image yang dipakai sudah punya user non-root bawaan dengan UID tertentu yang tidak bisa diubah lewat opsi --user.

sudo chown -R 1000:1000 ./src

11.4.2 SELinux dan Opsi Label :z / :Z

Pada distro Linux yang mengaktifkan SELinux secara default seperti Fedora, RHEL, atau CentOS, bind mount bisa ditolak aksesnya oleh kebijakan SELinux meski permission Unix biasa (UID/GID) sudah benar. Docker menyediakan opsi label tambahan :z dan :Z yang ditambahkan setelah opsi -v untuk mengatasi ini.

docker run -d --name demo-selinux -v /home/user/data:/data:z alpine sleep 3600

Label :z (huruf kecil) menandai bahwa direktori tersebut boleh dipakai bersama oleh beberapa container sekaligus. Label :Z (huruf besar) menandai direktori tersebut hanya dipakai eksklusif oleh container yang sedang di-mount, sehingga container lain tidak bisa mengaksesnya. Opsi ini hanya relevan di host Linux dengan SELinux aktif; di distro tanpa SELinux atau di macOS/Windows, label ini tidak berpengaruh apa-apa.

11.4.3 Troubleshooting Umum

Kalau container gagal menemukan file yang seharusnya ada lewat bind mount, langkah pertama adalah memastikan path host yang ditulis di opsi -v benar-benar mengarah ke lokasi yang dimaksud, bukan direktori kosong yang tidak sengaja dibuat otomatis oleh Docker karena salah ketik path. Periksa isi mount dari dalam container langsung lewat docker exec.

docker exec demo-app ls -la /app

Untuk memastikan konfigurasi mount sudah sesuai yang diharapkan, termasuk mode read-only dan opsi propagation-nya, periksa lewat docker inspect pada bagian Mounts.

docker inspect --format '{{json .Mounts}}' demo-app

Pada Docker Desktop di macOS dan Windows, bind mount ke direktori di luar direktori home atau drive yang sudah diizinkan lewat pengaturan file sharing Docker Desktop akan ditolak dengan error permission meski secara Unix permission terlihat benar. Tambahkan direktori yang dibutuhkan lewat menu Settings pada Docker Desktop, bagian Resources > File Sharing, supaya Docker Desktop mengizinkan bind mount ke path tersebut.

Kalau perubahan file di host tidak langsung terlihat di dalam container atau sebaliknya, terutama pada Windows dengan WSL2, pastikan direktori project berada di dalam filesystem Linux milik WSL2 (misalnya di bawah /home/user/), bukan di partisi Windows yang diakses lewat /mnt/c/. Docker Desktop merekomendasikan hal ini karena bind mount lintas filesystem Windows-Linux lewat WSL2 punya overhead performa I/O yang jauh lebih tinggi dibanding bind mount yang seluruhnya berada di dalam filesystem Linux WSL2.

MasalahPenyebab UmumSolusi
Permission denied saat baca/tulisUID proses container tidak cocok dengan owner file hostSamakan lewat --user atau chown di host
Akses ditolak meski permission Unix benarKebijakan SELinux aktif di host LinuxTambahkan label :z atau :Z pada opsi -v
Mount ke direktori kosong tak terdugaPath host salah ketik, otomatis dibuat oleh -vPastikan path benar; pertimbangkan --mount yang menolak path tidak ada
Bind mount ditolak di Docker DesktopPath belum diizinkan lewat pengaturan file sharingTambahkan direktori lewat Settings > Resources > File Sharing
Performa I/O lambat di WindowsBind mount lintas filesystem Windows-WSL2Pindahkan project ke dalam filesystem Linux WSL2