مدیریت داده‌ها و Volumeها در Docker

ماهیت موقت کانتینرها (Ephemeral Nature)

لایه‌ی خواندن و نوشتن کانتینرها به‌گونه‌ای طراحی شده است که موقت (Ephemeral) باشد. این یعنی:

  • اگر کانتینر یک پایگاه داده بدون متصل کردن Volume حذف شود (docker rm)، داده‌ها و تغییرات ثبت‌شده در لایه‌ی کانتینر از بین خواهند رفت.
  • کانتینرها به‌گونه‌ای طراحی شده‌اند که در صورت نیاز، بدون نگرانی از دست رفتن داده‌های اصلی بتوان آن‌ها را بازآفرینی یا با نسخه‌ی جدید جایگزین کرد (Stateless vs Stateful).

برای حل این مسئله و ذخیره‌سازی ماندگار داده‌ها (Persistent Storage)، داکر ۳ مکانیزم اصلی ارائه می‌دهد:

 1       ┌────────────────────────────────────────────────────────┐
 2       │                      Docker Host                       │
 3       │                                                        │
 4       │   [ Bind Mount ]         [ Named Volume ]   [ tmpfs ]  │
 5       │   /home/ubuntu/app       /var/lib/docker/   (Host RAM) │
 6       │          │                      │               │      │
 7       └──────────┼──────────────────────┼───────────────┼──────┘
 8                  │                      │               │
 9       ┌──────────▼──────────────────────▼───────────────▼──────┐
10       │                   Running Container                    │
11       └────────────────────────────────────────────────────────┘

انواع ذخیره‌سازی در Docker

۱. داکر والیوم (Named Volumes) - گزینه‌ی استاندارد و توصیه‌شده

والیوم‌ها دایرکتوری‌هایی هستند که مستقیماً توسط داکر مدیریت می‌شوند (به‌طور پیش‌فرض در مسیر /var/lib/docker/volumes/ روی سرور لینوکس).

  • سیستم‌عامل میزبان یا کاربران معمولی به محتوای آن دسترسی مستقیم ندارند.
  • مستقل از چرخه‌ی حیات کانتینرها هستند؛ اگر کانتینر پاک شود، Volume دست‌نخورده باقی می‌ماند.
  • گزینه‌ی استاندارد و توصیه‌شده برای ذخیره‌سازی ماندگار پایگاه‌های داده (مانند PostgreSQL، MySQL، MongoDB).

۲. بایند مانت (Bind Mounts)

اتصال مستقیم یک دایرکتوری یا فایل دلخواه از هاست لینوکسی به مسیری داخل کانتینر (مانند نگاشت /home/ubuntu/app/src به /app/src).

  • هر تغییری در فایل‌های سیستم میزبان داخل کانتینر دیده می‌شود و برعکس.
  • گزینه‌ی عالی برای محیط‌های توسعه (Live Reload کدهای برنامه‌نویسی) و قرار دادن فایل‌های تنظیماتی سرور (مانند کانفیگ Nginx).

۳. مانت موقت در رم (tmpfs Mount)

ذخیره‌سازی فایل‌ها روی حافظه‌ی موقت (RAM) سرور میزبان بدون نوشتن روی دیسک.

  • سرعت خواندن و نوشتن فوق‌العاده بالا.
  • با خاموش شدن کانتینر، داده‌ها پاک می‌شوند؛ مناسب نگهداری توکن‌های امنیتی موقت یا کش‌های پرسرعت.

دستورهای مدیریت Volume

 1# ایجاد یک والیوم جدید
 2docker volume create pg_data
 3
 4# مشاهده‌ی فهرست والیوم‌های موجود
 5docker volume ls
 6
 7# دیدن جزئیات و مسیر فیزیکی والیوم روی دیسک
 8docker volume inspect pg_data
 9
10# حذف یک والیوم خاص
11docker volume rm pg_data
12
13# پاک کردن تمام والیوم‌هایی که توسط هیچ کانتینری استفاده نمی‌شوند
14docker volume prune

نحوه‌ی اتصال Volume به کانتینر: -v در مقابل --mount

در داکر دو سینتکس برای اتصال فضای ذخیره‌سازی وجود دارد:

  1. سینتکس کلاسیک -v (کوتاه):
    1-v volume_name:/container/path
    2# یا برای Bind Mount:
    3-v /host/path:/container/path:ro
  2. سینتکس مدرن و خواناتر --mount (پیشنهاد در اتوماسیون و اسکریپت‌ها):
    1--mount type=volume,source=volume_name,target=/container/path
    2# یا برای Bind Mount:
    3--mount type=bind,source=/host/path,target=/container/path,readonly

آزمایش عملی: پایداری دیتابیس PostgreSQL با Named Volume

بیایید ماندگاری داده‌ها را با اجرای یک کانتینر دیتابیس تست کنیم:

گام ۱: اجرای دیتابیس با اتصال یک Volume اختصاصی

1docker run -d \
2  --name mydb \
3  -e POSTGRES_PASSWORD=mysecretpassword \
4  -v pgdata:/var/lib/postgresql/data \
5  postgres:16-alpine

گام ۲: ورود به دیتابیس و ایجاد یک جدول و رکورد

1docker exec -it mydb psql -U postgres

داخل محیط psql دستورات SQL زیر را وارد کنید:

1CREATE TABLE users (id SERIAL PRIMARY KEY, name VARCHAR(50));
2INSERT INTO users (name) VALUES ('TechStack Learner');
3SELECT * FROM users;
4\q

گام ۳: حذف کانتینر دیتابیس!

اکنون با اطمینان کانتینر را به اجبار متوقف و حذف می‌کنیم:

1docker rm -f mydb

گام ۴: اجرای یک کانتینر کاملاً جدید با همان والیوم قبلی

1docker run -d \
2  --name mydb_v2 \
3  -e POSTGRES_PASSWORD=mysecretpassword \
4  -v pgdata:/var/lib/postgresql/data \
5  postgres:16-alpine

گام ۵: بررسی بقای داده‌ها

1docker exec -it mydb_v2 psql -U postgres -c "SELECT * FROM users;"

خروجی نشان می‌دهد که اطلاعات دقیقاً در جای خود باقی مانده‌اند:

1 id |       name        
2----+-------------------
3  1 | TechStack Learner
4(1 row)

با این آزمایش دیدیم که با تخریب کانتینرها هیچ آسیبی به داده‌های پایدار وارد نمی‌شود.


مثال عملی Bind Mount در محیط توسعه

فرض کنید می‌خواهید صفحه‌ی اول یک وب‌سرور Nginx را بدون نیاز به ساخت مجدد ایمیج (docker build) به صورت زنده ویرایش کنید:

گام ۱: ساخت فایل اولیه و اجرای کانتینر با Bind Mount

1mkdir -p ~/site
2echo "<h1>Hello from Host Filesystem!</h1>" > ~/site/index.html
3
4docker run -d --name web -p 8080:80 \
5  -v /home/ubuntu/site:/usr/share/nginx/html:ro \
6  nginx:alpine

(پسوند :ro دسترسی کانتینر به فایل‌های سرور را Read-Only می‌کند تا امنیت حفظ شود).

گام ۲: تست خروجی اولیه با curl

1curl http://localhost:8080

خروجی زیر دریافت می‌شود:

1<h1>Hello from Host Filesystem!</h1>

گام ۳: تغییر مستقیم محتوای فایل روی هاست و بررسی زنده با curl

اکنون بدون ریستارت یا تغییر کانتینر، فایل index.html را روی هاست تغییر دهید:

1echo "<h1>Updated content without rebuilding container!</h1>" > ~/site/index.html

مجدداً با curl وضعیت را بسنجید:

1curl http://localhost:8080

خروجی بلافاصله تغییر را نمایش می‌دهد:

1<h1>Updated content without rebuilding container!</h1>

این آزمایش نشان می‌دهد که با Bind Mount، کانتینر مستقیماً فایل‌های مسیر هاست را می‌خواند؛ به همین دلیل این روش بهترین ابزار برای توسعه‌ی زنده (Live Development) بدون اتلاف وقت برای بازسازی ایمیج است.


منابع یادگیری

ویدیو

مستندات و مقالات