نحوه اشتراک گذاری داده بین کانتینرهای داکر در اوبونتو

نحوه اشتراک گذاری داده بین کانتینرهای داکر در اوبونتو

داکر یک ابزار محبوب کانتینرسازی است که برای فراهم کردن یک سیستم فایل برای برنامه‌های نرم‌افزاری استفاده می‌شود؛ سیستمی که شامل همه چیزهایی است که برای اجرا نیاز دارند. استفاده از کانتینرهای داکر تضمین می‌کند که نرم‌افزار در هر مکانی که مستقر شود، به یک شکل عمل خواهد کرد، زیرا محیط اجرایی آن یکسان است.

به طور کلی، کانتینرهای داکر موقتی هستند و فقط تا زمانی اجرا می‌شوند که دستوری که درون آن‌ها صادر شده به پایان برسد. با این حال، گاهی اوقات برنامه‌ها نیاز دارند تا به داده‌ها به صورت مشترک دسترسی داشته باشند یا داده‌ها را پس از حذف شدن یک کانتینر حفظ کنند. پایگاه‌های داده، محتوای تولید شده توسط کاربران برای یک وب‌سایت، و فایل‌های گزارش (log files) تنها چند نمونه از داده‌هایی هستند که گنجاندن آن‌ها در یک ایمیج داکر عملی یا ممکن نیست، اما برنامه‌ها نیاز دارند به آن‌ها دسترسی داشته باشند. دسترسی ماندگار به داده‌ها از طریق ولوم‌های داکر (Docker Volumes) فراهم می‌شود.

ولوم‌های داکر می‌توانند هم‌زمان با ایجاد یک کانتینر ساخته و متصل شوند، یا اینکه به صورت مستقل از هر کانتینری ساخته شده و بعداً به آن متصل شوند. در این مقاله، شما با چهار روش مختلف برای اشتراک‌گذاری داده بین کانتینرها آشنا خواهید شد.

پیش‌نیازها
برای دنبال کردن این مقاله، شما به یک سرور Ubuntu 22.04 با شرایط زیر نیاز دارید:

  • یک کاربر غیر ریشه (non-root) با دسترسی sudo. راهنمای "راه‌اندازی اولیه سرور با Ubuntu 22.04" توضیح می‌دهد که چگونه این کار را انجام دهید.
  • نصب بودن Docker با استفاده از دستورالعمل‌های مراحل 1 و 2 در راهنمای "چگونه Docker را بر روی Ubuntu 22.04 نصب و استفاده کنیم".

مرحله ۱.ایجاد یک Volume مستقل

در نسخه 1.9 داکر، دستور docker volume create معرفی شد که به شما اجازه می‌دهد یک ولوم را بدون ارتباط با هیچ کانتینر خاصی ایجاد کنید. شما از این دستور برای افزودن یک ولوم به نام DataVolume1 استفاده خواهید کرد:

docker volume create --name DataVolume1

نام ولوم نمایش داده می‌شود که نشان می‌دهد دستور با موفقیت اجرا شده است:

خروجی:

DataVolume1

برای استفاده از این ولوم، یک کانتینر جدید از ایمیج Ubuntu ایجاد می‌کنید. از فلگ --rm برای حذف خودکار کانتینر پس از خروج استفاده می‌شود. همچنین از -v برای مانت کردن (mount) ولوم جدید استفاده خواهید کرد. فلگ -v به نام ولوم، یک دونقطه، و سپس مسیر مطلقی که ولوم باید درون کانتینر ظاهر شود نیاز دارد. اگر دایرکتوری‌های موجود در مسیر در ایمیج وجود نداشته باشند، هنگام اجرای دستور ایجاد خواهند شد. اگر هم وجود داشته باشند، ولوم مانت‌شده محتوای موجود را پنهان خواهد کرد:

docker run -ti --rm -v DataVolume1:/datavolume1 ubuntu

در حالی که داخل کانتینر هستید، مقداری داده درون ولوم بنویسید:

echo "Example1" > /datavolume1/Example1.txt

از آنجا که از فلگ --rm استفاده کردید، کانتینر شما به طور خودکار پس از خروج حذف خواهد شد. اما ولوم شما همچنان در دسترس باقی خواهد ماند.

exit

برای بررسی اینکه ولوم روی سیستم وجود دارد، از دستور docker volume inspect استفاده کنید:

docker volume inspect DataVolume1

خروجی:

[
    {
        "CreatedAt": "2018-07-11T16:57:54Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/DataVolume1/_data",
        "Name": "DataVolume1",
        "Options": {},
        "Scope": "local"
    }
]

نکته: حتی می‌توانید داده‌ها را روی سیستم میزبان (host) در مسیری که به عنوان Mountpoint لیست شده مشاهده کنید. با این حال، باید از تغییر آن‌ها خودداری کنید، چون اگر برنامه‌ها یا کانتینرها از این تغییرات بی‌اطلاع باشند، ممکن است منجر به خراب شدن داده شود.

در مرحله بعد، یک کانتینر جدید راه‌اندازی کرده و DataVolume1 را به آن متصل کنید:

docker run --rm -ti -v DataVolume1:/datavolume1 ubuntu

محتوا را بررسی کنید:

cat /datavolume1/Example1.txt

خروجی:

Example1

از کانتینر خارج شوید:

exit

در این مثال، شما یک ولوم ایجاد کردید، آن را به یک کانتینر متصل کردید، و پایداری (ماندگاری) آن را بررسی نمودید.

مرحله ۲.ایجاد یک Volume که پس از حذف کانتینر باقی بماند

در مثال بعدی، شما یک ولوم را هم‌زمان با ایجاد کانتینر می‌سازید، سپس کانتینر را حذف کرده و ولوم را به یک کانتینر جدید متصل می‌کنید.

شما از دستور docker run برای ایجاد یک کانتینر جدید با استفاده از ایمیج پایه Ubuntu استفاده خواهید کرد. فلگ -t یک ترمینال در اختیار ما قرار می‌دهد، و فلگ -i اجازه می‌دهد که با آن تعامل کنیم. برای شفافیت بیشتر، از --name برای نام‌گذاری کانتینر استفاده می‌کنید.

فلگ -v به ما این امکان را می‌دهد که یک ولوم جدید ایجاد کنیم که نام آن را DataVolume2 قرار می‌دهید. شما با استفاده از دونقطه این نام را از مسیر مانت‌شدن آن در داخل کانتینر جدا می‌کنید. در نهایت، ایمیج پایه Ubuntu را مشخص می‌کنید و از دستور پیش‌فرض bash در Dockerfile ایمیج Ubuntu استفاده می‌کنید تا وارد یک پوسته شوید:

docker run -ti --name=Container2 -v DataVolume2:/datavolume2 ubuntu

نکته: فلگ -v بسیار انعطاف‌پذیر است. با کمی تغییر در نحو (syntax)، می‌تواند یک bind mount ایجاد کند یا یک ولوم نام‌گذاری شده باشد. اگر آرگومان اول با / یا ~/ شروع شود، شما در حال ایجاد یک bind mount هستید. اگر این بخش حذف شود، در حال ایجاد یک ولوم نام‌گذاری‌شده هستید. برای مثال:

  • -v /path:/path/in/container دایرکتوری /path را از میزبان در مسیر /path/in/container مانت می‌کند.
  • -v path:/path/in/container یک ولوم با نام path ایجاد می‌کند که هیچ ارتباطی با میزبان ندارد.

برای اطلاعات بیشتر درباره bind mount از میزبان، به راهنمای نحوه اشتراک‌گذاری داده بین یک کانتینر داکر و میزبان مراجعه کنید.

درون کانتینر، مقداری داده درون ولوم بنویسید:

echo "Example2" > /datavolume2/Example2.txt
cat /datavolume2/Example2.txt

خروجی:

Example2

از کانتینر خارج شوید:

exit

زمانی که کانتینر را مجدداً راه‌اندازی می‌کنید، ولوم به‌صورت خودکار مانت می‌شود:

docker start -ai Container2

بررسی کنید که آیا ولوم واقعاً مانت شده و داده‌ها همچنان وجود دارند:

cat /datavolume2/Example2.txt

خروجی:

Example2

در نهایت، خارج شده و پاک‌سازی را انجام دهید:

exit

داکر اجازه نمی‌دهد که ولومی که هنوز توسط یک کانتینر استفاده می‌شود، حذف شود. برای دیدن این موضوع، امتحان کنید:

docker volume rm DataVolume2

پیغام خطا به شما می‌گوید که ولوم هنوز در حال استفاده است و شناسه کامل کانتینر را نشان می‌دهد:

خروجی:

Error response from daemon: unable to remove volume: remove DataVolume2: volume is in use - [d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63]

شما می‌توانید از شناسه موجود در پیام بالا برای حذف کانتینر استفاده کنید:

docker rm d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63

خروجی:

d0d2233b668eddad4986313c7a4a1bc0d2edaf0c7e1c02a6a6256de27db17a63

حذف کانتینر تاثیری بر ولوم ندارد. شما می‌توانید با استفاده از دستور docker volume ls ببینید که ولوم هنوز روی سیستم وجود دارد:

docker volume ls

خروجی:

DRIVER              VOLUME NAME
local               DataVolume2

و می‌توانید با دستور زیر آن را حذف کنید:

docker volume rm DataVolume2

در این مثال، شما یک ولوم داده خالی را هم‌زمان با ایجاد یک کانتینر ساختید. در مثال بعدی، بررسی خواهید کرد که چه اتفاقی می‌افتد اگر یک ولوم را در مسیری مانت کنید که از قبل درون کانتینر داده دارد.

مرحله ۳.ایجاد یک Volume از یک دایرکتوری موجود همراه با داده

به‌طور کلی، ایجاد ولوم به‌صورت مستقل با docker volume create و ایجاد ولوم هم‌زمان با ایجاد کانتینر معادل هستند، با یک استثنا: اگر هنگام ایجاد کانتینر، یک ولوم را تعریف کنید و مسیری را ارائه دهید که در ایمیج پایه حاوی داده باشد، آن داده‌ها به ولوم کپی خواهند شد.

برای مثال، شما یک کانتینر ایجاد خواهید کرد و ولومی را در مسیر /var مانت می‌کنید — دایرکتوری‌ای که در ایمیج پایه دارای داده است:

docker run -ti --rm -v DataVolume3:/var ubuntu

تمام محتوای دایرکتوری /var از ایمیج پایه به ولوم کپی می‌شود، و شما می‌توانید این ولوم را در یک کانتینر جدید مانت کنید.

از کانتینر فعلی خارج شوید:

exit

این بار، به‌جای تکیه بر دستور پیش‌فرض bash ایمیج پایه، دستور ls را اجرا می‌کنید تا محتوای ولوم را بدون ورود به پوسته نمایش دهید:

docker run --rm -v DataVolume3:/datavolume3 ubuntu ls datavolume3

دایرکتوری datavolume3 اکنون حاوی یک کپی از محتوای دایرکتوری /var ایمیج پایه است:

خروجی:

backups
cache
lib
local
lock
log
mail
opt
run
spool
tmp

احتمالاً مانت کردن /var/ به این صورت در عمل مفید نخواهد بود، اما اگر ایمیج سفارشی خود را ایجاد کرده‌اید، این روش می‌تواند راهی آسان برای نگه‌داری داده‌ها باشد.

مرحله ۴.اشتراک‌گذاری داده بین چند کانتینر داکر

تا اینجا، شما یک ولوم را فقط به یک کانتینر در هر زمان متصل کرده‌اید. در بسیاری از موارد، می‌خواهید چند کانتینر از یک ولوم داده مشترک استفاده کنند. این کار به‌راحتی قابل انجام است، اما یک نکته مهم وجود دارد: در حال حاضر، داکر قفل‌گذاری فایل (file locking) را مدیریت نمی‌کند. اگر چند کانتینر نیاز دارند به‌طور هم‌زمان در ولوم بنویسند، برنامه‌های داخل آن‌ها باید طوری طراحی شده باشند که از ذخیره‌سازی‌های اشتراکی پشتیبانی کنند تا از خرابی داده جلوگیری شود.

ایجاد Container4 و DataVolume4

از docker run استفاده کنید تا یک کانتینر با نام Container4 و یک ولوم به نام DataVolume4 بسازید:

docker run -ti --name=Container4 -v DataVolume4:/datavolume4 ubuntu

سپس یک فایل ایجاد کرده و مقداری متن بنویسید:

echo "This file is shared between containers" > /datavolume4/Example4.txt

از کانتینر خارج شوید:

exit

اکنون، در ترمینال میزبان، یک کانتینر جدید بسازید که ولوم را از Container4 مانت کند.

ایجاد Container5 و مانت کردن ولوم‌های Container4

کانتینر Container5 را ایجاد می‌کنید و ولوم‌های Container4 را مانت می‌کنید:

docker run -ti --name=Container5 --volumes-from Container4 ubuntu

بررسی پایداری داده:

cat /datavolume4/Example4.txt

خروجی:

This file is shared between containers

سپس مقداری متن از Container5 اضافه کنید:

echo "Both containers can write to DataVolume4" >> /datavolume4/Example4.txt

از کانتینر خارج شوید:

exit

اکنون بررسی کنید که آیا داده‌ها همچنان از طریق Container4 قابل مشاهده هستند.

مشاهده تغییرات ایجادشده در Container5

با اجرای مجدد Container4 تغییرات را بررسی کنید:

docker start -ai Container4

بررسی محتوا:

cat /datavolume4/Example4.txt

خروجی:

This file is shared between containers
Both containers can write to DataVolume4

پس از اطمینان از اینکه هر دو کانتینر می‌توانند به داده‌ها بخوانند و بنویسند، از کانتینر خارج شوید:

exit

باز هم یادآوری می‌شود که داکر قفل‌گذاری فایل انجام نمی‌دهد، بنابراین برنامه‌ها باید خودشان به قفل‌گذاری توجه کنند. برای جلوگیری از تغییرات ناخواسته، می‌توان ولوم را به‌صورت فقط‌خواندنی مانت کرد. در ادامه، نحوه انجام این کار را خواهید دید.

اجرای Container6 با مانت فقط‌خواندنی Volume

پس از مانت شدن یک ولوم، به‌جای آن‌که آن را مانند فایل‌سیستم لینوکس از حالت مانت خارج کنید، می‌توانید یک کانتینر جدید ایجاد کرده و آن را به شیوه‌ای که می‌خواهید مانت کنید. برای فقط‌خواندنی کردن ولوم، :ro را به انتهای نام کانتینر در --volumes-from اضافه کنید:

docker run -ti --name=Container6 --volumes-from Container4:ro ubuntu

برای بررسی حالت فقط‌خواندنی، سعی کنید فایل مثال را حذف کنید:

rm /datavolume4/Example4.txt

خروجی:

rm: cannot remove '/datavolume4/Example4.txt': Read-only file system

در نهایت، از کانتینر خارج شده و کانتینرها و ولوم آزمایشی خود را پاک‌سازی کنید:

exit

پاک‌سازی:

docker rm Container4 Container5 Container6
docker volume rm DataVolume4

نتیجه‌گیری

در این آموزش، شما یک ولوم داده ایجاد کردید که امکان نگه‌داری داده‌ها پس از حذف کانتینر را فراهم می‌کرد. شما ولوم‌های داده را بین چند کانتینر به اشتراک گذاشتید، با این هشدار که برنامه‌ها باید خودشان قفل‌گذاری فایل را مدیریت کنند تا از خرابی داده جلوگیری شود. در نهایت، نحوه مانت کردن یک ولوم مشترک به‌صورت فقط‌خواندنی را نیز نشان دادید.

اگر علاقه‌مند به یادگیری نحوه اشتراک‌گذاری داده بین کانتینرها و سیستم میزبان هستید، راهنمای نحوه اشتراک‌گذاری داده بین کانتینر داکر و میزبان را ببینید.

منبع DigitalOcean 

۱۹
۱۴۰۴/۳/۱۰