
نحوه اشتراک گذاری داده بین کانتینرهای داکر در اوبونتو
داکر یک ابزار محبوب کانتینرسازی است که برای فراهم کردن یک سیستم فایل برای برنامههای نرمافزاری استفاده میشود؛ سیستمی که شامل همه چیزهایی است که برای اجرا نیاز دارند. استفاده از کانتینرهای داکر تضمین میکند که نرمافزار در هر مکانی که مستقر شود، به یک شکل عمل خواهد کرد، زیرا محیط اجرایی آن یکسان است.
به طور کلی، کانتینرهای داکر موقتی هستند و فقط تا زمانی اجرا میشوند که دستوری که درون آنها صادر شده به پایان برسد. با این حال، گاهی اوقات برنامهها نیاز دارند تا به دادهها به صورت مشترک دسترسی داشته باشند یا دادهها را پس از حذف شدن یک کانتینر حفظ کنند. پایگاههای داده، محتوای تولید شده توسط کاربران برای یک وبسایت، و فایلهای گزارش (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
