تمهيد
بشكل عام، نستعمل حاويات Docker لمرة وحيدة فقط، وهي تعمل إلى أن ينتهي تنفيذ الأمر الموكل إليها. لكن في بعض الأحيان تحتاج التطبيقات إلى الوصول إلى بيانات أو حفظها بعد حذف الحاوية. أمثلة عن البيانات التي تحتاج التطبيقات إلى الوصول إليها تتضمن قواعد البيانات، والمحتوى المولّد من قِبل المستخدم لمواقع الويب، وملفات السجلات. يمكن الوصول إلى تلك البيانات بشكلٍ دائم باستخدام حجوم Docker (أي Docker Volumes).
المتطلبات المسبقة
-
خادوم أوبنتو 16.04 (أو 14.04) مضبوطٌ كما في درس «الإعداد الابتدائي لخادوم أوبنتو 14.04»، بما في ذلك إعداد حساب مستخدم عادي لكنه يملك امتيازات الجذر (root) عبر الأداة
sudo
. - برمجية Docker مثبّتة على حاسوبك
ملاحظة: صحيحٌ أننا نفترض أنَّنا سنستعمل Docker على أوبنتو 16.04، لكن أوامر docker
التي تتعامل مع حجوم Docker والمذكورة في هذا الدرس يجب أن تعمل عملًا صحيحًا على بقية الأنظمة لطالما كانت Docker مثبّتةً عليها وأُضيف المستخدم sudo
إلى المجموعة docker
.
يمكن إنشاء حجوم Docker ووصلها بأمرٍ واحد ألا وهو الأمر المُستخدَم لإنشاء الحاوية، أو يمكن إنشاء الحجوم بشكل مستقلٍ عن أيّة حاوية ثم وصلها إليها لاحقًا. سنناقش في هذا الدرس أربع طرائق مختلفة لمشاركة البيانات بين الحاويات.
أولًا: إنشاء حجم مستقل
أتى الأمر docker volume create
مع إصدار 1.9 من Docker والذي يسمح لك بإنشاء حجم دون ربطه بأية حاوية. سنستخدم هذا الأمر لإنشاء حجم باسم DataVolume1
:
docker volume create --name DataVolume1
إذا عُرِض الاسم، فذلك يُشير إلى نجاح تنفيذ الأمر السابق:
DataVolume1
لكي نستعمل هذا الحجم، علينا إنشاء حاوية جديدة مبنية على صورة ubuntu مستعملين الخيار --rm
لحذف الحاوية تلقائيًا بعد خروجنا منها، وسنستخدم الخيار -v
لوصل الحجم الجديد. الخيار -v
يتطلب ذكر اسم الحجم متبوعًا بنقطتين رأسيتين :
ثم المسار المطلق لمكان وصل الحجم داخل الحاوية. إذا لم يكن المجلد المذكور في المسار السابق موجودًا في صورة التوزيعة، فسيُنشَأ ثم سيُنفَّذ الأمر السابق؛ وفي حال كان المجلد موجودًا، فسيؤدي وصل الحجم إليه إلى إخفاء المحتوى الموجود في الصورة الأصلية.
docker run -ti --rm -v DataVolume1:/datavolume1 ubuntu
لنكتب بعض البيانات إلى الحجم قبل إغلاق الحاوية:
root@802b0a78f2ef:/# echo "Example1" > /datavolume1/Example1.txt
ولاستعمالنا الخيار --rm
عند إنشاء الحاوية، فستُحذَف الحاوية تلقائيًا عند خروجنا منها. لكن الحجم سيبقى متاحًا للوصول.
root@802b0a78f2ef:/# exit
يمكننا أن نتحقق أنَّ الحجم ما يزال موجودًا في النظام عبر الأمر docker volume inspect
:
docker volume inspect DataVolume1
الناتج:
[
{
"Name": "DataVolume1",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/datavolume1/_data",
"Labels": null,
"Scope": "local"
}
]
ملاحظة: يمكننا أيضًا تفحص البيانات الموجودة في المسار المذكور في سطر Mountpoint
لكن لا يُستحسَن تعديلها، لأنَّ ذلك قد يؤدي إلى حدوث عطب في البيانات إن كانت الحاوية تعمل وتجري تعديلات على تلك الملفات.
لنبدأ الآن حاويةً جديدةً ونربط الحجم DataVolume1
إليها:
docker run --rm -ti -v DataVolume1:/datavolume1 ubuntu
سنُنفِّذ الأمر الآتي داخل الحاوية:
root@d73eca0365fc:/# cat /datavolume1/Example1.txt
الناتج:
Example1
لنخرج الآن من الحاوية بالأمر exit
.
ثانيًا: إنشاء حجم مرتبط بحاوية لكن سيبقى موجودًا بعد حذفها
سنُنشِئ في المثال الآتي حجمًا وحاويةً في آنٍ واحد، ومن ثم سنحذف الحاوية، ثم سنربط الحجم إلى حاويةٍ جديدة.
سنستخدم الأمر docker run
لإنشاء حاوية جديدة بناءً على صورة ubuntu
، وسيؤدي استخدام الخيار -t
إلى منحنا وصولًا إلى الطرفية، والخيار -i
سيسمح لنا بالتفاعل مع الحاوية. ولغرض التوضيح، سأستخدم الخيار --name
لتحديد اسم للحاوية، ثم سأستخدم الخيار -v
لإنشاء حجم جديد، وسنسميّه DataVolume2
، وسنستخدم النقطتين الرأسيتين لفصل الاسم عن مسار وصل الحجم في الحاوية. وفي النهاية سنطلب إنشاء الحاوية لتبدأ تنفيذها بالأمر الافتراضي الموجود في ملف Docker لصورة Ubuntu (الذي هو الأمر bash
) لكي نحصل على وصول إلى الصدفة (shell):
docker run -ti --name=Container2 -v DataVolume2:/datavolume2 ubuntu
ملاحظة: الخيار -v
هو خيارٌ مرنٌ جدًا، إذ يستطيع إنشاء وصل ترابطي، أو يمكنه إنشاء حجم جديد بتعديلٍ بسيط جدًا في شكله. فلو بدأ أوّل وسيطٍ بشرطة مائلة /
أو ~/
فسيُنشِئ وصلًا ترابطيًا، لكن إن حذفت الشرطة في أوّل وسيط، فسيُنشِئ حجمًا.
-
-v /path:/path/in/container
وصل المسار/path
في الجهاز المضيف إلى/path/in/container
في الحاوية. -
-v path:/path/in/container
إنشاء حجم باسمpath
دون علاقة بالمضيف.
ولمّا كنا داخل الحاوية، فلنكتب بعض البيانات إلى الحجم:
root@87c33b5ae18a:/# echo "Example2" > /datavolume2/Example2.txt
root@87c33b5ae18a:/# cat /datavolume2/Example2.txt
الناتج:
Example2
سنخرج من الحاوية باستخدام الأمر exit
.
سنُعيد الآن تشغيل الحاوية مرةً أخرى، وسيتم وصل الحجم تلقائيًا.
docker start -ai Container2
لنتأكد من أنَّ الحجم قد وصِلَ إلى الحاوية وما تزال البيانات موجودةً فيه:
root@87c33b5ae18a:/# cat /datavolume2/Example2.txt
الناتج:
Example2
لنخرج مرةً أخرى من الحاوية بالأمر exit
.
لن تسمح لنا Docker بحذف الحجم إذا كان مرتبطًا بحاوية، لننظر ماذا سيحدث لو جربنا ذلك:
docker volume rm DataVolume2
ستخبرنا الرسالة الآتية أنَّ الحجم ما يزال مستخدم وستعطينا المُعرِّف الكامل للحاوية:
Error response from daemon: Unable to remove volume,
volume still in use: remove DataVolume2: volume is in use -
[719f98391ecf1d6f0f053ffea1bbd84cd2dc9cf6d31d5a4f348c60d98392804c]
يمكننا استخدام المُعرِّف السابق لحذف الحاوية:
docker rm 719f98391ecf1d6f0f053ffea1bbd84cd2dc9cf6d31d5a4f348c60d98392804c
لن يؤثر حذف الحاوية على الحجم المرتبط بها، وما زال موجودًا في النظام، ونستطيع التحقق من ذلك باستخدام الأمر docker volume ls
:
docker volume ls
الناتج:
DRIVER VOLUME NAME
local DataVolume2
نستطيع الآن استخدام الأمر docker volume rm
لحذف الحجم بتمرير اسمه إلى الأمر السابق:
docker volume rm DataVolume2
أنشأنا في هذا المثال حجمًا فارغًا مع الحاوية الذي يرتبط بها في آنٍ واحد. أما في المثال القادم فسنرى ماذا سيحدث لو أنشأنا حجمًا ووصلناه إلى مجلدٍ فيه بيانات موجودة مسبقًا في الحاوية.
ثالثًا: إنشاء حجم وربطه بمجلدٍ فيه بيانات
عمومًا، لا يكون هنالك فرقٌ بين إنشاء حجم باستخدام الأمر docker volume create
وبين إنشائه عند تشغيل الحاوية، لكن هنالك استثناءٌ وحيدٌ لهذه القاعدة، ويحدث عندما نُنشِئ حجمًا في نفس وقت إنشاء الحاوية وكان المسار الذي نريد ربط الحجم فيه مجلدًا موجودًا في الصورة الأصلية وفيه بيانات، وفي هذه الحالة ستُنسَخ البيانات الموجودة في ذاك المجلد إلى الحجم.
كمثال عن الحالة السابقة، سنُنشِئ حاويةً ونصل الحجم الجديد إلى المجلد /var
الموجود مسبقًا في صورة التوزيعة والذي يحتوي على بيانات:
docker run -ti --rm -v DataVolume3:/var ubuntu
جميع المحتوى الموجود في مجلد /var
في الصورة الأصلية سيُنسَخ إلى الحجم، ثم يمكننا وصل الحجم إلى الحاوية الجديدة. وفي هذه المرة، سنُنفِّذ الأمر ls
بدلًا من الأمر الافتراضي bash
، والذي سيُظهِر محتويات الحجم دون الحاجة إلى الدخول إلى الصدفة:
docker run --rm -v DataVolume3:/datavolume3 ubuntu ls DataVolume3
كما توقعنا، سيحتوي الحجم DataVolume3
على نسخةٍ من محتويات مجلد /var
في الصورة الأصلية:
backups
cache
lib
local
lock
log
mail
opt
run
spool
tmp
من غير المرجّح أن نصل المجلد /var
بهذه الطريقة، لكن قد تستفيد من المعلومات السابقة إذا أردت إنشاء صورة خاصة بك وتريد طريقةً سهلةً للحفاظ على البيانات.
سنشرح في المثال الآتي كيفية مشاركة الحجم مع أكثر من حاوية.
رابعًا: مشاركة البيانات بين أكثر من حاوية Docker
كل ما فعلناه منذ بداية هذا الدرس هو وصل الحجم إلى حاوية واحدة فقط بنفس الوقت، لكننا نرغب عادةً بالسماح بمشاركة البيانات بين أكثر من حاوية عبر وصل الحجم إلى عدِّة حاوية معًا. وهذا سهلٌ جدًا، لكن هنالك مشكلة محورية: لا تدعم Docker حاليًا ميزة التعامل مع قفل الملفات (file locking)، فلو احتاجت أكثر من حاوية إلى الكتابة على الحجم، فيجب أن تكون البرمجيات الموجودة في تلك الحاويات مصممةً لكي تكتب إلى أماكن تخزين البيانات المشتركة، لتجنّب تلف البيانات.
إنشاء الحاوية Container4 والحجم DataVolume4
سنستخدم الأمر docker run
لإنشاء حاوية جديدة باسم Container4
ووصل حجم جديد إليها:
docker run -ti --name=Container4 -v DataVolume4:/datavolume4 ubuntu
سنُنشِئ الآن ملفًا ونضع فيه بعض المحتوى النصي:
root@db6aaead532b:/# echo "This file is shared between containers" > /datavolume4/Example4.txt
ثم سنخرج من الحاوية بالأمر exit
.
سنعود الآن إلى سطر الأوامر في الجهاز المضيف، حيث سنُنشِئ حاويةً جديدةً ونصل فيها الحجم DataVolume4
.
إنشاء الحاوية Container5 ووصل الحجم الذي كان موصولًا في Container4
سنُنشِئ حاويةً جديدةً باسم Container5
ونصل فيها الحجم الذي كان موصولًا في Container4:
docker run -ti --name=Container5 --volumes-from Container4 ubuntu
root@81e7a6153d28:/# cat /datavolume4/Example4.txt
This file is shared between containers
لنضف بعض النصوص إلى أحد الملفات من الحاوية الثانية:
root@81e7a6153d28:/# echo "Both containers can write to DataVolume4" >> /datavolume4/Example4.txt
ثم سنخرج من الحاوية بالأمر exit
.
سنتأكد الآن أنَّ البيانات الجديدة أصبحت متاحةً للحاوية Container4.
رؤية التغييرات التي أجريناها في Container5
لنتحقق من أنَّ الحاوية Container5 قد كتبت البيانات على حجم DataVolume4 بإعادة تشغيل الحاوية Container4:
docker start -ai Container4
root@db6aaead532b:/# cat /datavolume4/Example4.txt
This file is shared between containers
Both containers can write to DataVolume4
بعد أن تأكدنا من إمكانية القراءة والكتابة إلى الحجم من كلا الحاويتين، فسنخرج من الحاوية بالأمر exit
.
أكرِّر أنَّ Docker لا تملك ميزةً لقفل الملفات، لذا يجب أن تقفل التطبيقاتُ الملفاتَ بنفسها. لكن من الممكن وصل حجم Docker للقراءة فقط لكي نضمن عدم حدوث تلف في البيانات نتيجةً لخطأٍ ما، وذلك عبر إضافة الخيار :ro
.
تشغيل الحاوية Container6 ووصل الحجم للقراءة فقط
نستطيع –بعد وصل الحجم إلى الحاوية– أن نفصله ثم نصله مرةً أخرى للقراءة فقط، لكننا نستطيع أيضًا إنشاء حاوية تصل الحجم كما نشاء مباشرةً. وذلك بإضافة :ro
بعد اسم الحاوية التي سنحاول وصل الحجم المرتبط بها:
docker run -ti --name=Container6 --volumes-from Container4:ro ubuntu
سنتحقق من أنَّ الحجم موصولٌ للقراءة فقط بمحاولتنا حذف الملف الذي أنشأناه سابقًا:
root@ab63aebe534c:/# rm /datavolume4/Example4.txt
rm: cannot remove '/datavolume4/Example4.txt': Read-only file system
بعد إغلاق هذه الحاوية (كالمعتاد، بالأمر exit
) فيمكننا حذف الحاويات التي أنشأناها إضافةً إلى الحجم:
docker rm Container4 Container5 Container6
docker volume rm DataVolume4
لقد رأينا في هذا المثال كيفية مشاركة البيانات بين حاويتين باستخدام الحجوم، بالإضافة إلى طريقة وصل الحجوم للقراءة فقط.
الخلاصة
أنشأنا في هذا الدرس حجم بيانات الذي يسمح لنا بالاحتفاظ بالبيانات حتى بعد حذفنا للحاوية. وشاركنا حجمًا بين عدِّة حاويات، ونوهنا إلى أهمية أن تكون التطبيقات المستعملة في الحاويات قادرةً على قفل الملفات لمنع تلف البيانات. وفي النهاية شاهدنا كيف يمكن وصل الحجم للقراءة فقط.
إذا كنتَ مهتمًا بكيفية مشاركة البيانات بين الحاويات والنظام المضيف، فأنصحك بقراءة درس «كيفية مشاركة البيانات بين حاوية Docker والمضيف».
ترجمة -وبتصرّف- للمقال How To Share Data between the Docker Container and the Hostلصاحبته Melissa Anderson
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.