ข้ามไปยังเนื้อหา

Bind Mounts

Bind mount map path เฉพาะเจาะจงบนเครื่อง host ของคุณโดยตรงเข้าไปใน container ต่างจาก named volume ตรงที่คุณเลือกเองว่าข้อมูลจะอยู่ที่ไหนบน host — Docker ไม่ได้จัดการ path ให้

Host filesystem: /home/user/myapp/src
↕ bind mount
Container filesystem: /app/src

การเปลี่ยนแปลงใดๆ ที่เกิดขึ้นฝั่ง host จะมองเห็นได้ทันทีภายใน container และในทางกลับกันด้วย ทำให้ bind mounts เหมาะสำหรับการพัฒนา: editor ของคุณแก้ไขไฟล์บน host และ process ที่รันอยู่ภายใน container เห็นการอัปเดตทันที — ไม่ต้อง rebuild

Short -v syntax:

Terminal window
docker run -v /host/path:/container/path myimage

Long --mount syntax (แนะนำสำหรับ scripts — ไม่มีความกำกวม):

Terminal window
docker run \
--mount type=bind,source=/host/path,target=/container/path \
myimage

ในการพัฒนาคุณแทบจะต้องการ mount ไดเรกทอรีทำงานปัจจุบันเสมอ:

Terminal window
docker run --rm -v $(pwd):/app -w /app node:22-alpine node server.js

$(pwd) ขยายเป็น absolute path ของ host ณ เวลา runtime นี่เป็น pattern มาตรฐานสำหรับการรัน code โดยไม่ต้อง build image ใหม่ทุกครั้งที่มีการเปลี่ยนแปลง

Terminal window
# Mount source ของคุณเข้า container ที่ /app
# flag -w กำหนด working directory ภายใน container
docker run -d --name dev-server \
-v $(pwd)/src:/app/src \
-p 3000:3000 \
node:22-alpine \
node /app/src/server.js

ตอนนี้แก้ไข src/server.js บน host ของคุณ ถ้า process ภายใน container ดู filesystem อยู่ (เช่น ด้วย nodemon) จะ restart อัตโนมัติ ไม่จำเป็นต้อง rebuild image สำหรับการเปลี่ยนแปลง code ทุกครั้ง

เพิ่ม :ro เพื่อทำให้ mount เป็น read-only จากมุมมองของ container container สามารถอ่านไฟล์ได้แต่เขียนไม่ได้:

Terminal window
docker run --rm \
-v $(pwd)/config:/etc/myapp/config:ro \
myimage

ด้วย --mount syntax:

Terminal window
docker run --rm \
--mount type=bind,source=$(pwd)/config,target=/etc/myapp/config,readonly \
myimage

มีประโยชน์สำหรับการ inject ไฟล์ configuration จาก host เข้า container โดยไม่ให้ container เขียนทับโดยบังเอิญ

snippet ด้านล่างสร้างไฟล์บน host (จำลองด้วย echo ในขั้นตอน setup) mount ไดเรกทอรีเข้า container และอ่านไฟล์จากภายใน container — สาธิตการแชร์ไฟล์แบบ live

# 1. Create a directory with a file to share
mkdir -p /tmp/bindtest && echo 'shared from host' > /tmp/bindtest/hello.txt

# 2. Mount it into a container and read the file
docker run --rm -v /tmp/bindtest:/data alpine cat /data/hello.txt

# 3. Write from inside the container back to the host
docker run --rm -v /tmp/bindtest:/data alpine sh -c "echo 'written by container' > /data/from-container.txt"

# 4. Check the file now exists on the host path
ls -la /tmp/bindtest/
cat /tmp/bindtest/from-container.txt

# 5. Clean up
rm -rf /tmp/bindtest
ตัวเลือกBenefitCost
Bind mountแก้ไขไฟล์บน host แล้วเห็นผลใน container ทันที เหมาะกับ live reload ตอนพัฒนาผูกกับ layout ของ host เครื่องนั้น ย้ายไป host อื่นต้องมี path เดียวกัน
Named volumeDocker จัดการพื้นที่จัดเก็บให้ พกพาข้าม host ได้ต้องเข้า container เพื่อดูไฟล์ ไม่สามารถเปิดด้วย editor บน host ได้ตรงๆ
  • ใช้ bind mount เก็บข้อมูลฐานข้อมูลใน production แทนที่จะใช้ named volume ทำให้ deploy ไป host อื่นแล้ว path ไม่ตรงกัน ข้อมูลหาย
  • ลืมว่า bind mount เขียนทับสิทธิ์ไฟล์ (permission) ตาม user ของ container ทำให้ไฟล์บน host เปลี่ยนเจ้าของโดยไม่ตั้งใจ
  • Mount ทั้งไดเรกทอรี node_modules จาก host เข้า container ทำให้ dependency ที่ build บน host คนละ OS ขัดแย้งกับที่ต้องใช้ใน container

💡 ตัวอย่างจากของจริง

official Postgres และ MySQL image แนะนำ named volume สำหรับ /var/lib/postgresql/data หรือ /var/lib/mysql เสมอ ไม่ใช่ bind mount เพราะ production ต้องการความสามารถพกพาที่ bind mount ให้ไม่ได้ bind mount เหมาะกับ source code ตอน dev เท่านั้น

ความแตกต่างสำคัญระหว่าง bind mount และ named volume คืออะไร?
expression ใดใน shell ที่ขยายเป็นไดเรกทอรีทำงานปัจจุบันในคำสั่ง `docker run`?
การเพิ่ม `:ro` ใน bind mount ทำอะไร?
ทำไม bind mounts ถึงเหมาะสำหรับการพัฒนาในเครื่องแต่ไม่แนะนำสำหรับ production?