قبل 3 أيام من العام الجديد ، كانت هناك مهمة لنقل برنامجنا إلى العميل من خلال المدير ، على محرك أقراص محمول. البرنامج عبارة عن منصة خدمات ميكروية تحتوي على عشرات الصور لرسو السفن مع العديد من الإعدادات ومخطط دفة طوله كيلومتر واحد. ما كان لدينا:
- مدير في موسكو (لست من هناك)
- نوافذ
- لا يوجد تفاعل مباشر (وإذا كان الأمر كذلك ، لم يساعد ذلك حقًا)
- عامل ميناء لا
PFF ، اعتقدت! سآخذ Golang ، كتابة برنامج ، ترجمة لنظام التشغيل Windows.
... وبعد 5 ساعات أدركت تسرع استنتاجاتي. في تلك اللحظة ، تذكرت ضحك نيلسون لأول مرة. ها ها الذي كان يطاردني طوال الوقت الذي قضيته في دراسة القضية.
معظم الأمثلة التي وجدت تتطلب dockerd. نصان لا يستخدمان dockerd ، تم العثور عليهما بعد ساعة من googling ، واحد واثنين . ساعدني الخيار الأول على فهم عملية الحصول على جميع طبقات الصور وملفات التكوين ، لكن من المستحيل استخدامها مع Windows. أشار الخيار الثاني إلى أنه لم يكن هناك فقط العديد من التجزئة المومض على الشاشة ، وتحديدا هذا FIXME . يمكن للمرء ، بالطبع ، التوقف عند هذا الحد ، إنه يعمل! نقل للذهاب ليست صعبة. ولكن كيف يمكن التحقق من أن صور المدير اتضح أنها بنفس الشكل الموجود في سجلنا؟ لكن بأي حال من الأحوال! لذلك ، قمت للتو بتحميل الصور إلى وحدة التخزين المشتركة ، وقمت بتنزيلها باستخدام الأمر docker save ، وشاركت الرابط. وهدأت على هذا.
في اليوم الرابع من الإجازات ، التي سئمت منها إلى حد كبير ، فكرت فكرة تنزيل وتجميع صورة عامل الإرساء بشكل صحيح مرة أخرى ، وتوغلت في رمز moby لبضع ساعات.
ما كان لدي هذه المرة:
- فهم كيفية الحصول على جميع الطبقات
أخذ Python "في متناول اليد" واستناداً إلى هذا البرنامج النصي ، قررت إصلاحه. في اليوم الثاني ، قررت أن أكتب السيناريو من الصفر. أتذكر عن الحرف اليدوية الخاصة بي للحصول على إذن الصياغة ، لقد قمت ببساطة بنسخ جزء من الكود من هناك ، بالإضافة إلى التطورات التي قمت بها بالفعل عند تحرير البرنامج النصي. لم تكن هناك مشاكل في الترخيص وتنزيل هذه البيانات ، ولكن ظهرت أسئلة:
- ما هي التجزئة التي يتم عرضها عند تنفيذ أمر سحب عامل ميناء؟
- ما هي التجزئة التي تستخدم لتسمية الدلائل داخل صورة القطران؟
- كيفية إنشاء أرشيف tar بحيث يتطابق مجموع التحقق مع الصورة الأصلية؟
للدراسة ، اخترت صورة أوبونتو: 18.04
تم حفظ صورة sha256sum عبر docker save
- 257cab9137419a53359d0ed76f680fe926ed3645238357bdcdb84070a8f26cd0.
> docker pull ubuntu:18.04 18.04: Pulling from library/ubuntu 2746a4a261c9: Downloading [==============> ] 6.909MB/26.69MB 4c1d20cdee96: Download complete 0d3160e1d0de: Download complete c8e37668deea: Download complete Digest: sha256:250cc6f3f3ffc5cdaa9d8f4946ac79821aafb4d3afc93928f0de9336eba21aa4 Status: Downloaded newer image for ubuntu:18.04 docker.io/library/ubuntu:18.04
محتويات كرة الطائرة الصورة
tar tvf ubuntu.tar drwxr-xr-x 0 root root 0 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/ -rw-r--r-- 0 root root 3 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/VERSION -rw-r--r-- 0 root root 477 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/json -rw-r--r-- 0 root root 991232 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/layer.tar drwxr-xr-x 0 root root 0 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/ -rw-r--r-- 0 root root 3 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/VERSION -rw-r--r-- 0 root root 477 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/json -rw-r--r-- 0 root root 15872 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/layer.tar -rw-r--r-- 0 root root 3411 Dec 19 11:21 549b9b86cb8d75a2b668c21c50ee092716d070f129fd1493f95ab7e43767eab8.json drwxr-xr-x 0 root root 0 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/ -rw-r--r-- 0 root root 3 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/VERSION -rw-r--r-- 0 root root 1264 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/json -rw-r--r-- 0 root root 3072 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/layer.tar drwxr-xr-x 0 root root 0 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/ -rw-r--r-- 0 root root 3 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/VERSION -rw-r--r-- 0 root root 401 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/json -rw-r--r-- 0 root root 65571328 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/layer.tar -rw-r--r-- 0 root root 432 Jan 1 1970 manifest.json -rw-r--r-- 0 root root 88 Jan 1 1970 repositories
التكوين الصورة
{ ... "rootfs": { "type": "layers", "diff_ids": [ "sha256:2dc9f76fb25b31e0ae9d36adce713364c682ba0d2fa70756486e5cedfaf40012", "sha256:9f3bfcc4a1a8a676da07287a1aa6f2dcc8e869ea6f054c337593481a5bb1345e", "sha256:27dd43ea46a831c39d224e7426794145fba953cd7309feccf4d5ea628072f6a2", "sha256:918efb8f161b4cbfa560e00e8e0efb737d7a8b00bf91bb77976257cd0014b765" ] } ... }
تم حل السؤال الأول بسرعة كافية ، ساعدت الوثائق https://github.com/opencontainers/image-spec/blob/master/config.md . التجزئات التي تظهر عند تشغيل أمر سحب عامل الإرساء هي سلاسل هوية محسوبة من قائمة diff_ids الخاصة ببيان صورة التكوين ، حيث تكون السلسلة الأولى معرف دائمًا هي الأولى من قائمة diff_ids ، أما العناصر اللاحقة فهي مبالغ تجزئة من السلسلة (chain_id[i-1] + " " + diff_id[i])
. رمز لبناء chainID chainID:
def chain_ids(ids: list) -> list: chain = list() chain.append(ids[0]) if len(ids) < 2: return ids nxt = list() nxt.append("sha256:" + hashlib.sha256(f'{ids[0]} {ids[1]}'.encode()).hexdigest()) nxt.extend(ids[2:]) chain.extend(chain_ids(nxt)) return chain
تعد إضافة بادئة باسم الخوارزمية ، في هذه الحالة "sha256:" ، إلزامية ويتم تضمينها في متطلبات معيار opencontainers ، أي يجب أن تكون السلسلة من النموذج "algorithm: hash".
قضى أمسيتين على سؤال حول تسمية الدليل. لفترة طويلة بما فيه الكفاية نظرت إلى شفرة مصدر عامل الخفي وأوه! معجزة! تمكنت من العثور على رمز الجيل هنا وهنا . لإنشاء اسم الدليل ، تحتاج إلى حساب التجزئة من تكوين طبقة json. يوجد في Docker العديد من إصدارات التكوين وقبل استخدام مشغل docker 1.9 ، تم استخدام تكوينات الإصدار v1. لم يقل قال من القيام به! ومرة أخرى ، تنشأ صورة ظلية نيلسون. بعد تصحيح قصير أدركت أن المشكلة كانت مختبئة في جيل json. في Python ، قد يختلف ترتيب البيانات في القاموس عن ترتيب البيانات في json الذي تم إنشاؤه من هذا القاموس. سيكون ترتيب البيانات في json مختلفًا ، وبناءً على ذلك ، سيكون تجزئة البيانات أيضًا مختلفة. اضطررت للذهاب إلى OrderedDict ، قبل تسجيل ترتيب البيانات المطلوب فيها. زاد هذا حجم الرمز بمقدار مرة ونصف.
يبدو أن كل شيء تم تصحيحه ، أقوم بتشغيل البرنامج النصي و ... في مكان ما بعمق ، ينبثق HA-HA سيئ السمعة! لا يتطابق التجزئة الأخير. مرة أخرى ، أدرس الكود وأرى ، وهذا هو تنسيق v1 آخر يحتوي على جميع المعلومات حول الصورة ، والتي يمكن رؤيتها باستخدام docker inspect
. إضافة OrderDict آخر خصيصا له ، واستكمال التعليمات البرمجية و ... HA HA!
كانت الساعة 5 صباحًا بالفعل ولم يفكر رأسي حقًا ، لذا بعد النوم عدت لمشاهدة الرمز. تبحث مرارا وتكرارا على رمز الجيل جاء عبر خط . كم كنت سعيدا لرؤية ذلك. قبل أن أراها ، كانت هناك أفكار لبناء مرفاع بلدي جاك الاسود و تسجيل البيانات. أقوم بتشغيل debug وتنفيذ docker save
و ... ليس أمرًا سخيفًا على الإطلاق ، في نظام docker-Desktop لنظام التشغيل mac يوجد حد لطول السطر في سجل 947 حرفًا وكسر التكوين الذي تم إنشاؤه إلى \"
. بعد تنفيذ كل هذه الخطوات في Linux ، تمكنت من الحصول على التكوين طبقة من الإصدار الأول ، على أساسها كتبت الكود ، وتمكنت من الحصول على التجزئة المطلوب للطبقة الأخيرة.تتجزي التجزئة لجميع الملفات هي نفسها ، تم تسمية الدلائل بنفس طريقة الصورة الأصلية ، لقد حان الوقت لجمع أرشيف tar ... HAHA!
لا يتطابق حجم الملف ، اقرأ https://github.com/opencontainers/image-spec/blob/master/layer.md وتنسيق أرشيف tar . القيمة الافتراضية هي 10240 بايت ، وحجم الأرشيف الذي جمعته أكبر من 9216 بايت. في البداية اعتقدت أنه كان من الضروري تقليل حجم الكتلة إلى 1024 بايت ، والذي تبين أنه غير صحيح ، ونتيجة لذلك ، فإن حجم الكتلة البالغ 512 بايت يعادل حجم المحفوظات.
tarfile.RECORDSIZE = 512
يحتوي السطر الأول من الأرشيف المنشأ حديثًا على المجلد الجذر "/". هذا الخيار غير مناسب ، لذلك ، أكمل الكود عن طريق مسح محتويات المجلد وإضافته بشكل فردي إلى الأرشيف ، بعد أن رتبته سابقًا.
أخيرًا ، تمكنا من تحقيق نفس حجم الملف ، ومظهر موحد للأدلة ، ولكن هذا ليس كل شيء. يجب أن يكون للملفات والدلائل ، باستثناء manifest.json والمستودعات ، في الأرشيف سمات st_atime ، st_mtime تساوي st_ctime. بالنسبة إلى ملفات manifest.json ومجموعات الاستجمام ، يجب أن تكون سمات st_atime و st_mtime و st_ctime مؤرخة في بداية عصر 1970-01-01 00:00
. يجب تعيين جميع التواريخ وفقًا للمنطقة الزمنية ، على التوالي. منذ أن قمت بجميع الأعمال في نظام التشغيل mac ، لاحظت وجود اختلاف واحد. عند حفظ الصورة في Linux ، تبدو قائمة الملفات الموجودة في الأرشيف كما يلي:
tar tvf ubuntu.tar drwxr-xr-x 0/0 0 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/ -rw-r--r-- 0/0 3 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/VERSION -rw-r--r-- 0/0 477 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/json -rw-r--r-- 0/0 991232 Dec 19 11:21 07adecfcb06a1142a69c3e769cb38f2d4ef9d772726ce1e65bc6dbd4448cccc9/layer.tar drwxr-xr-x 0/0 0 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/ -rw-r--r-- 0/0 3 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/VERSION -rw-r--r-- 0/0 477 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/json -rw-r--r-- 0/0 15872 Dec 19 11:21 3e1d90747aa9d2a7ec6e9693bdd490dff8528b9aec4a2fac2300824e4ba3a60e/layer.tar -rw-r--r-- 0/0 3411 Dec 19 11:21 549b9b86cb8d75a2b668c21c50ee092716d070f129fd1493f95ab7e43767eab8.json drwxr-xr-x 0/0 0 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/ -rw-r--r-- 0/0 3 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/VERSION -rw-r--r-- 0/0 1264 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/json -rw-r--r-- 0/0 3072 Dec 19 11:21 b0474230e27ddbba2f46397aac85d4d2fd748064ed9c0ff1e57fec4f063fcf6b/layer.tar drwxr-xr-x 0/0 0 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/ -rw-r--r-- 0/0 3 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/VERSION -rw-r--r-- 0/0 401 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/json -rw-r--r-- 0/0 65571328 Dec 19 11:21 c8ba25f7db9f70220ac92449b238a0697f9eb580ef4f905225a333fc0a5e8719/layer.tar -rw-r--r-- 0/0 432 Jan 1 1970 manifest.json -rw-r--r-- 0/0 88 Jan 1 1970 repositories
بخلاف القائمة الموجودة في بداية المقال ، على نظام Linux ، يتم حفظ الأرشيف مع العلم الرقمي فقط. هناك متغيرين في كائن tarinfo المسؤول عن هذا ، tarinfo.uname و tarinfo.gname. والمشكلة الثانية في نظام التشغيل mac هي عدم وجود مجموعة جذر ، يتم إصلاحها باستخدام متغير tarinfo.gid في نفس كائن tarinfo. حسنًا ، يبدو أن كل شيء ينشئ أرشيفًا ...

بالنسبة لجميع الملفات ، يتقارب التجزئة ، وتتشابه أسماء الدلائل والملفات ، وتتقارب السمات st_atime ، st_mtime و st_ctime مع الأصل ، والحقوق في الملفات هي نفسها تمامًا. شهد فتح كل المحفوظات في محرر سداسي عشرية اختلافًا بسيطًا:

النافذة العليا هي النسخة الأصلية ، الأرشيف السفلي الذي جمعته.
فهم تنسيق القطران. بعد اسم الدليل ، تكون قيمة حقوق الملف (المستطيل البرتقالي). الفرق هو أن المعلومات حول الكائن الذي يتم إضافته إلى الأرشيف لا تتم إضافتها إلى حقوق الدليل. تشير القيمة 40755 المشار إليها في الحقوق إلى أن هذا هو الدليل الذي يحتوي على أذونات 755 ، و 100644 هو ملف ذو أذونات 644. المستطيل الأحمر عبارة عن سلسلة سحرية ويتم الحكم عليها بواسطة رمز tarfile و ustar\000
سلسلة السحر ، ويستخدم فقط في تنسيقات PAX و USTAR. لا يناسب تنسيق PAX على الإطلاق ، ويستخدم نوعًا خاصًا من الرأس. المستطيل الأزرق عبارة عن مبلغ تدقيق ويختلف بسبب استخدام تنسيقات مختلفة لحقوق الكتابة إلى ملف ورأس سحري.
أقوم بتغيير تنسيق الأرشيف إلى USTAR ، لكن ليس من الواضح ما يجب القيام به مع أذونات ملفات التسجيل. هنا وهنا يحدث السحر ، لم أعمل مطلقًا مع النظام الثماني ولا أفهم سبب الحاجة إلى علامة الضم هنا (ربما يشارك شخص ما في التعليقات المعرفة). اضطررت إلى إضافة العديد من المطبوعات لمعرفة البيانات التي تصل مع الوسائط والبيانات التي يتم استخدامها لتشكيل كتلة الأرشيف. أخذ عددًا صحيحًا من الموضع الثاني من كتلة البيانات ، كان 16877 ، وقادها إلى حساب التفاضل والتكامل الثماني ، اتضح أن هذه القيمة هي 0o40755
، وهذا 0o40755
ما أحتاج إليه. بمجرد تجاوز الدالتين get_info و _create_header ، وحذف & 0o7777
منهم (لم يتبادر إلى ذهني أي شيء آخر) ، تمكنت من جمع أرشيف tar مع علامة sha256 التي تزامنت مع النسخة الأصلية.
ملاحظة: أثناء كتابة مقال ، تم تحديث صورة أوبونتو: 18.04 على hub.docker.com. لذلك اضطررت لتحميل الصورة على دايجست. لم تعد كميات التجزئة تتطابق مع النسخة الأصلية نظرًا لحقيقة أن Digest تمت كتابتها بدلاً من العلامة ، وإلا كانت الصور متطابقة.
كان الاكتشاف الثاني بالنسبة لي هو عدم وجود ملف مستودعات في الأرشيف عند حفظ صورة بعلامة مفقودة باستخدام docker save
.
رمز العمل الكامل هنا: https://github.com/myback/docker_pull
صورة نيلسون مانز ، بالإضافة إلى ضحكته "HA-HA" هي ملك FOX :)