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