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

Volumes vs Bind Mounts

คุณสมบัติNamed VolumeBind Mount
Path จัดการโดยDockerคุณ
ต้องการ host pathไม่ต้องต้องการ
ความสามารถพกพาสูง — ทำงานได้บน host ทุกเครื่องต่ำ — path ต้องมีอยู่ในทุก host
ประสิทธิภาพปรับแต่งโดย Docker storage driverใช้ host filesystem โดยตรง (เร็วบน Linux ช้ากว่าบน macOS/Windows)
การสำรองข้อมูลdocker volume inspect + tar containerคัดลอกไฟล์โดยตรงจาก host path
กรณีใช้งานทั่วไปไฟล์ฐานข้อมูล state ของแอป uploadsSource code ไฟล์ config ในการพัฒนา
ใช้ใน production ได้ได้ไม่ค่อยได้ (ขึ้นอยู่กับ layout ของ host)
  • คุณต้องการให้ข้อมูลรอดชีวิตจากการสร้าง container ใหม่ (ฐานข้อมูล object storage cache)
  • คุณ deploy ไปยัง remote host หรือ environment CI/CD ที่ host path อาจแตกต่างกัน
  • คุณต้องการให้ Docker เป็นเจ้าของ lifecycle ของพื้นที่จัดเก็บ
  • คุณกำลังพัฒนาในเครื่องและต้องการ live code reload โดยไม่ต้อง rebuild image
  • คุณต้องการ inject ไฟล์ config จาก host เข้า container ณ เวลา runtime
  • คุณกำลังรัน tools (linters, compilers) ที่ผลิต output ที่คุณต้องการโดยตรงบน host

ทั้งสองประเภทรองรับ read-only mounts container สามารถอ่านข้อมูลได้แต่เขียนไปยัง mount target ไม่ได้

Named volume แบบ read-only:

Terminal window
docker run --rm -v mydata:/app/data:ro alpine ls /app/data

Bind mount แบบ read-only:

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

ด้วย --mount syntax (ทั้งสองประเภท):

Terminal window
# Volume
docker run --rm --mount type=volume,source=mydata,target=/app/data,readonly myimage
# Bind
docker run --rm --mount type=bind,source=$(pwd)/config,target=/etc/app/config,readonly myimage

Read-only mounts เป็น security best practice เมื่อ container ต้องการเพียงแค่อ่านข้อมูล — ป้องกัน process ที่ถูก compromise หรือมีข้อบกพร่องจากการเขียนทับไฟล์สำคัญ

snippet ด้านล่างสาธิต mount ทั้งสองประเภทเคียงข้างกัน เพื่อให้คุณสังเกตความแตกต่างในเซสชันเดียว

# --- Named volume ---
docker volume create compare-vol

# Write via container
docker run --rm -v compare-vol:/data alpine sh -c "echo 'from named volume' > /data/note.txt"

# Read from a new container (data persists)
docker run --rm -v compare-vol:/data alpine cat /data/note.txt

# --- Bind mount ---
mkdir -p /tmp/compare-bind
echo 'from bind mount' > /tmp/compare-bind/note.txt

# Read from container via bind mount
docker run --rm -v /tmp/compare-bind:/data alpine cat /data/note.txt

# --- Read-only mount ---
docker run --rm -v /tmp/compare-bind:/data:ro alpine sh -c "cat /data/note.txt && echo 'trying to write...' && echo 'blocked' > /data/note.txt || echo 'Write blocked as expected'"

# Clean up
docker volume rm compare-vol
rm -rf /tmp/compare-bind
ตัวเลือกBenefitCost
Named volumeDocker จัดการเอง พกพาข้าม host ได้ สำรองข้อมูลง่ายด้วย throwaway containerเรียกดูไฟล์ตรงจาก host filesystem ไม่ได้ ต้อง mount เข้า container ก่อน
Bind mountเข้าถึง path บน host ได้โดยตรง เหมาะกับ dev workflow ที่ต้องแก้ไฟล์บ่อยๆผูกกับโครงสร้างไดเรกทอรีของ host เครื่องนั้น ย้ายข้าม environment ยาก
  • เลือก bind mount สำหรับเก็บข้อมูลฐานข้อมูล production เพราะ “เห็นไฟล์ตรงๆ ง่ายดี” ทั้งที่ named volume คือตัวเลือกที่ถูกต้องกว่า
  • รัน docker compose down -v ทั้งที่ตั้งใจแค่หยุด container ทำให้ named volume ที่ผูกกับ service ถูกลบไปด้วย
  • ไม่เคยตั้งแผนสำรองข้อมูลให้ named volume เพราะเข้าใจผิดว่า Docker จัดการ backup ให้อัตโนมัติ

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

official Postgres/MySQL Docker image documentation แนะนำให้ใช้ named volume mount ที่ /var/lib/postgresql/data เป็น pattern มาตรฐานสำหรับ production ส่วน bind mount ใช้เฉพาะตอนพัฒนาเพื่อความสะดวกในการแก้ไข config หรือ source code

ตัวเลือกพื้นที่จัดเก็บใดมีความสามารถพกพาสูงกว่าข้ามเครื่อง host ต่างๆ?
ตำแหน่งที่ถูกต้องของ flag `:ro` สำหรับ read-only bind mount ด้วย syntax `-v` คืออะไร?
ทำไม bind mounts ถึงทำงานช้ากว่าบน macOS และ Windows เมื่อเทียบกับ Linux?
Read-only mount เป็น security best practice เพราะป้องกันอะไร?