اگر کانتینر را پاک میکنید و دادهٔ دیتابیس یا آپلودها هم با آن میرود، مشکل این است که روی لایهٔ نوشتنی کانتینر نوشتهاید نه روی Volume. Volume را داکر مدیریت میکند، از عمر کانتینر جداست، و طبق مستند رسمی روش ترجیحی ماندگاری داده بین کانتینرهاست. این آموزش صفحهٔ Volumes در Docker Docs را دنبال میکند.
پیشنیازهایی که جا میماند
نقشها را جدا کنید: named volume نام مشخص دارد و برای اشتراک بین کانتینرها مناسب است؛ anonymous volume نام تصادفی میگیرد و با --rm ممکن است همراه کانتینر حذف شود؛ bind mount مسیر میزبان را مستقیم سوار میکند و موضوع این آموزش نیست. Engine باید روی میزبان در حال اجرا باشد و برای تمرین به دسترسی اجرای docker نیاز دارید. مستند میگوید در کل --mount صریحتر از -v است.
ساخت Volume و سوار کردن روی کانتینر
- یک Volume نامدار بسازید: docker volume create my-vol. با docker volume ls ببینید در فهرست آمده است.
- کانتینر را با سوار کردن Volume اجرا کنید. شکل توصیهشده: docker run --mount type=volume,src=my-vol,dst=/data … که src نام Volume و dst مسیر داخل کانتینر است.
- اگر شکل کوتاهتر میخواهید: docker run -v my-vol:/data … و برای فقطخواندنی -v my-vol:/data:ro یا در --mount کلید ro.
- داخل مسیر مقصد یک فایل آزمایشی بنویسید، کانتینر را متوقف و حذف کنید، دوباره با همان src و dst بالا بیاورید؛ اگر فایل مانده، ماندگاری درست کار میکند.
- جزئیات را با docker volume inspect my-vol ببینید؛ فیلد Mountpoint مسیر واقعی روی میزبان را نشان میدهد (مدیریتشده توسط داکر).
- اگر Volume خالی را روی مسیری سوار کنید که در ایمیج از قبل فایل دارد، بهطور پیشفرض آن محتوا به Volume کپی میشود. برای جلوگیری، از volume-nocopy در --mount استفاده کنید.
- Volumeهای بلااستفاده را فقط وقتی مطمئنید پاک کنید: docker volume prune. Volume در حال استفاده حذف نمیشود، ولی prune روی دادهٔ یتیم برگشتناپذیر است.
چرخهٔ عمر و تفاوت با لایهٔ کانتینر
با حذف کانتینر لایهٔ نوشتنی از بین میرود؛ محتوای Volume میماند مگر خود Volume را حذف کنید. یک Volume را میتوان همزمان به چند کانتینر سوار کرد. اگر Volume غیرخالی را روی مسیر موجود سوار کنید، فایلهای قبلی آن مسیر در کانتینر مخفی میشوند (مثل Mount کردن فلش روی /mnt). راهحل ساده برای دیدن دوبارهٔ آن فایلها معمولاً ساخت مجدد کانتینر بدون آن Mount است.
نکتهٔ ایمنی داده
برای دادهٔ مهم از named volume با نام روشن استفاده کنید، نه anonymous پراکنده. قبل از prune، docker volume ls و inspect را بخوانید. Volume برای دسترسی آسان از میزبان ابزار اول نیست؛ اگر باید از روی میزبان فایل را ویرایش کنید، bind mount را جداگانه در مستند Bind mounts ببینید. بکاپ Volume را بخشی از کار عملیاتی بدانید، نه کار اختیاری.
خطاهای رایج
- بعد از recreate داده نیست: روی مسیر Volume ننوشتهاید یا نام Volume عوض شده است.
- پوشه داخل کانتینر خالی بهنظر میرسد: Volume غیرخالی روی محتویات قبلی سوار شده و آنها را پوشانده است.
- از میزبان فایل را نمیبینید: Volume را داکر مدیریت میکند؛ دنبال مسیر اپ در خانهٔ کاربر نگردید مگر Mountpoint را از inspect بخوانید.
- بعد از prune داده رفته: Volume unused بوده و آگاهانه حذف شده است.
جمعبندی و منبع
Volume نامدار بسازید، با --mount به مسیر دادهٔ اپ بچسبانید، با حذف و ساخت مجدد کانتینر ماندگاری را تست کنید، و prune را فقط روی Volumeهای بلااستفاده بزنید. مرجع: Volumes | Docker Documentation. برای دیتابیس از named volume استفاده میکنید یا هنوز به پوشهٔ داخل کانتینر تکیه دارید؟
برای دیتابیس و صف و آپلود کاربر همیشه named volume با نام معنیدار بسازید تا در compose و اسکریپتها قابل ارجاع باشد. anonymous volume برای دادهٔ موقت آزمایشی است و با --rm ممکن است غافلگیرتان کند.
اگر چند سرویس باید به یک داده بخوانند، همان named volume را به چند کانتینر با dst مناسب سوار کنید و سطح دسترسی داخل کانتینر را جدی بگیرید. برای نوشتن فقط از یک سرویس، بقیه را ro سوار کنید تا خرابکاری کمتر شود.
وقتی Volume خالی روی مسیر ازپیشپر ایمیج سوار میشود، کپی اولیه مفید است؛ اما اگر نمیخواهید آن کپی انجام شود volume-nocopy را در --mount بگذارید. برعکس، Volume غیرخالی محتویات قبلی مسیر را میپوشاند—این رفتار مستند است نه باگ.
قبل از مهاجرت یا بکاپ، Mountpoint را از docker volume inspect بخوانید و از ابزار رسمی یا رویهٔ تیم برای کپی امن استفاده کنید؛ مستقیم دستکاری فایلهای زندهٔ دیتابیس روی Mountpoint بدون توقف سرویس ریسک دارد.
مرجع گزینههای --mount و تفاوت Volume با bind mount همان صفحهٔ Volumes در Docker Docs است؛ برای ویرایش زنده از میزبان به مستند Bind mounts بروید نه اینکه Volume را دور بزنید.
در Docker Compose هم معمولاً named volume را در بخش volumes تعریف میکنید و به سرویس mount میکنید؛ منطق ماندگاری همان است که در docker run دیدید. اگر بین bind و volume مردد هستید، این را ملاک بگیرید: دادهٔ اپ که فقط کانتینر باید ببیند → volume؛ فایلی که روی میزبان ویرایش میکنید → bind mount.