صور الحاويات
كل مستودع في Arkvory هو أيضًا سجل حاويات. يدفع Docker وPodman وBuildx وcontainerd وHelm وORAS إليه ويسحب منه ببروتوكول OCI Distribution. وتُخزَّن طبقات الصور وملفات البيان (manifests) كمُخرَجات (artifacts) عادية. وتنطبق عليها أذونات المستودع والحصص وعمليات التحقق من SHA-256 والنسخ الاحتياطية والمرايا كما على أي ملف آخر.
قبل أن تبدأ
تحتاج إلى:
- عنوان الخادم مع HTTPS وشهادة موثوقة، مثل
arkvory.example. راجع HTTPS. - مستودع، مثل
releases. - مفتاح: رمز وصول شخصي أو مفتاح خدمة. راجع الحسابات والمفاتيح.
يرد السجل على جذر المضيف، تحت /v2/. ولا يمكنه العمل تحت بادئة مسار مثل https://example.com/arkvory/، لأن Docker لا يدعم ذلك. ويجب أن يمرّر الوكيل العكسي /v2/ دون تغيير، وألا يخزّن أجسام الطلبات مؤقتًا (buffer). في nginx اضبط client_max_body_size 0 وأوقف التخزين المؤقت للطلبات.
أسماء الصور
للمرجع إلى الصورة (image reference) الصيغة التالية:
<host>/<repository>/<image>:<tag>
<host>/<repository>/<image>@sha256:<digest>المقطع الأول من المسار هو مستودع Arkvory. وهو حد الوصول: لا يرى المفتاح إلا المستودعات الممنوحة له. والباقي هو اسم الصورة، من مكوّن واحد أو أكثر.
| المرجع | المستودع | الصورة | جزء المرجع |
|---|---|---|---|
arkvory.example/releases/web:1.4 | releases | web | الوسم 1.4 |
arkvory.example/releases/team/web:1.4 | releases | team/web | الوسم 1.4 |
arkvory.example/qa/tools/builder@sha256:… | qa | tools/builder | الملخص (digest) |
| الجزء | القاعدة |
|---|---|
| المستودع | أحرف صغيرة وأرقام و_ و-. يبدأ بحرف أو رقم. حتى 64 حرفًا. |
| الصورة | مكوّنات مفصولة بـ /. يتألف المكوّن من أحرف صغيرة وأرقام تربطها . أو _ أو __ أو شرطات. حتى 200 حرف في المجموع. |
| الوسم | أحرف وأرقام و_ و. و-. يبدأ بحرف أو رقم أو _. حتى 128 حرفًا. |
| الملخص | sha256: و64 رقمًا سداسي عشريًا بأحرف صغيرة. تُرفض الخوارزميات الأخرى. |
يُرفض المرجع الذي لا يحتوي على جزء الصورة، مثل arkvory.example/web:1.4، بالخطأ NAME_INVALID: يؤخذ web على أنه المستودع، ويكون اسم الصورة فارغًا.
تسجيل الدخول
يأخذ السجل مفتاح Arkvory ككلمة مرور للمصادقة HTTP Basic. ولا يُتحقق من اسم المستخدم: استخدم أي اسم، مثل اسم مهمة CI. ويمكن للطلب أيضًا إرسال المفتاح بصيغة Authorization: Bearer <key>. ولا تحتاج إلى خدمة رموز منفصلة.
docker login arkvory.example -u ci --password-stdin < ~/.arkvory/keyGet-Content C:\Private\arkvory.key | docker login arkvory.example -u ci --password-stdinتسجّل بقية العملاء الدخول بالطريقة نفسها:
podman login arkvory.example -u ci --password-stdin < ~/.arkvory/key
helm registry login arkvory.example -u ci --password-stdin < ~/.arkvory/key
oras login arkvory.example -u ci --password-stdin < ~/.arkvory/key| المفتاح | يُستخدم لـ |
|---|---|
رمز وصول شخصي، النطاق read | السحب على محطة عمل |
رمز وصول شخصي، النطاق read-write | الدفع من محطة عمل |
| مفتاح خدمة | CI/CD ووكلاء النشر. وهو النوع الوحيد من المفاتيح القادر على حذف الصور. |
| مفتاح ملف من ملف مفاتيح الخادم | مالك التثبيت والتكاملات الأقدم (read أو write) |
ينتهي الرمز الشخصي. وبعد ذلك يحصل كل طلب على 401 UNAUTHORIZED: أنشئ رمزًا جديدًا وسجّل الدخول مرة أخرى. يحفظ Docker المفتاح في ~/.docker/config.json ما لم تضبط credential helper. احمِ هذا الملف أو استخدم مخزن بيانات اعتماد (credential store).
الدفع والسحب
docker tag web:1.4 arkvory.example/releases/team/web:1.4
docker push arkvory.example/releases/team/web:1.4
docker pull arkvory.example/releases/team/web:1.4
docker pull arkvory.example/releases/team/web@sha256:<digest>ما يفعله السجل:
- الطبقة التي يملكها المستودع بالفعل لا تُخزَّن مرة أخرى، حتى لو استخدمتها صورة أخرى.
- لا تُشارك الطبقات بين المستودعات. فطلب ربط (mount) طبقة من مستودع آخر يحصل على جلسة رفع عادية، فيرسل العميل الطبقة مرة أخرى.
- تُفحص كل طبقة وكل ملف بيان مقابل ملخص SHA-256 الخاص به. وعند عدم التطابق لا يُخزَّن شيء ويُعاد
DIGEST_INVALID. - لا يُقبل ملف البيان إلا إذا كان كل ما يشير إليه موجودًا بالفعل في المستودع: الإعداد (config) وطبقات الصورة، أو ملفات بيان المنصات في الفهرس (index). ويجب أن تكون ملفات بيان المنصات في الصورة نفسها التي فيها فهرسها. وإلا يكون الرد
MANIFEST_BLOB_UNKNOWN. - يدعم تنزيل الطبقات طلبات
Range.
يقبل السجل أنواع ملفات البيان التالية:
| نوع الوسائط (Media type) | الاستخدام |
|---|---|
application/vnd.oci.image.manifest.v1+json | صور OCI ومخططات Helm ومُخرَجات ORAS |
application/vnd.oci.image.index.v1+json | الصور متعددة المنصات، وذاكرة BuildKit المؤقتة في السجل |
application/vnd.docker.distribution.manifest.v2+json | صور Docker (المخطط 2) |
application/vnd.docker.distribution.manifest.list.v2+json | صور Docker متعددة المنصات |
يحمل ملف البيان schemaVersion: 2 وحجمه 4 MiB على الأكثر. ولا يُدعم المخطط 1 في Docker. ويؤخذ النوع من ترويسة Content-Type أو من الحقل mediaType في ملف البيان، ويجب أن يتفقا. ويعيد السحب ملف البيان تمامًا كما دُفع، بنوع الوسائط الخاص به. ولا يحوّل السجل بين الصيغ.
الصور متعددة المنصات
docker buildx build --platform linux/amd64,linux/arm64 \
-t arkvory.example/releases/team/web:1.4 --push .يدفع Buildx ملف بيان كل منصة بملخصه، ثم الفهرس (index) تحت الوسم. وتذهب كلها إلى اسم الصورة نفسه، كما يتطلب السجل.
ذاكرة البناء المؤقتة
يمكن لمنشئ BuildKit يستطيع تصدير ذاكرة مؤقتة، مثل منشئ docker buildx ببرنامج التشغيل docker-container، أن يحتفظ بذاكرته المؤقتة في السجل داخل Arkvory:
docker buildx build \
--cache-from type=registry,ref=arkvory.example/releases/team/web:cache \
--cache-to type=registry,ref=arkvory.example/releases/team/web:cache,mode=max \
-t arkvory.example/releases/team/web:1.4 --push .يسرد فهرس الذاكرة المؤقتة الطبقات وإعداد الذاكرة المؤقتة. ويخزّنها Arkvory ككتل (blobs) تتبع الصورة، ويحميها كطبقات أي ملف بيان مخزَّن.
مخططات Helm
يخزّن Helm المخططات كمُخرَجات OCI. بعد helm registry login:
helm push web-1.4.0.tgz oci://arkvory.example/releases/charts
helm pull oci://arkvory.example/releases/charts/web --version 1.4.0
helm install web oci://arkvory.example/releases/charts/web --version 1.4.0يصبح المخطط الصورة charts/web بالوسم 1.4.0 في المستودع releases. وليس في Arkvory مستودع مخططات كلاسيكي بملف index.yaml.
مُخرَجات ORAS
يخزّن ORAS أي ملفات كطبقات في ملف بيان OCI:
oras push arkvory.example/releases/tools/settings:1.0 ./settings.json:application/json
oras pull arkvory.example/releases/tools/settings:1.0واجهة Referrers API غير متوفرة: يجيب /v2/<name>/referrers/<digest> بالرمز 404. وعندئذ تحتفظ العملاء التي تتبع مواصفة OCI، مثل ORAS، بالمُخرَجات المرفقة تحت وسوم تحمل اسم الملخص بدلًا من ذلك.
الوسوم والملخصات
- دفع ملف بيان تحت وسم ينقل الوسم. ويبقى ملف البيان الذي كان الوسم يسمّيه من قبل في السجل، ويمكن سحبه بملخصه.
- الدفع بالملخص (
PUT /v2/<name>/manifests/sha256:…) يخزّن ملف البيان دون وسم. ويجب أن يكون الملخص هو SHA-256 لجسم الطلب. - تُسرد الوسوم بترتيب البايتات، لذا تأتي الأحرف الكبيرة قبل الصغيرة.
لسرد وسوم صورة:
curl -fsS -u "ci:$ARKVORY_KEY" https://arkvory.example/v2/releases/team/web/tags/listالرد هو {"name": "releases/team/web", "tags": [...]}. استخدم n لحجم الصفحة (100 افتراضيًا، وبحد أقصى 1000) وlast لآخر وسم في الصفحة السابقة. وعندما توجد وسوم أخرى، تحتوي ترويسة Link على عنوان الصفحة التالية.
للعثور على ملخص وسم:
curl -fsSI -u "ci:$ARKVORY_KEY" \
https://arkvory.example/v2/releases/team/web/manifests/1.4 | grep -i docker-content-digestلا يوجد فهرس لكل الصور (/v2/_catalog). وفي وحدة التحكم تظهر الطبقات وملفات البيان ضمن مُخرَجات المستودع بالتسمية oci، وأسماؤها هي ملخصاتها. استخدم التصفية حسب التسمية في المُخرَجات لعرضها.
حذف الصور وتحرير المساحة
تحذف الصور عبر واجهة السجل البرمجية. وليس في سطر أوامر Docker أمر لذلك: استخدم curl أو oras manifest delete أو أداة سجل أخرى.
| الطلب | الأثر |
|---|---|
DELETE /v2/<name>/manifests/<tag> | يزيل الوسم فقط. ويبقى ملف البيان ويمكن سحبه بملخصه. |
DELETE /v2/<name>/manifests/<digest> | يزيل ملف البيان وكل وسم يشير إليه |
DELETE /v2/<name>/blobs/<digest> | يُرفض بالرمز 405. تغادر الطبقات مع ملفات بيانها. |
يحتاج كلا الحذفين إلى مفتاح خدمة بالإجراء artifact.delete في المستودع. ولا تستطيع الرموز الشخصية وجلسات وحدة التحكم ومفاتيح الملفات حذف الصور. ويجيب الحذف بالرمز 202.
curl -fsS -X DELETE -H "Authorization: Bearer $ARKVORY_CLEANUP_KEY" \
https://arkvory.example/v2/releases/team/web/manifests/sha256:<digest>كيف تتحرر المساحة:
- ما دام ملف البيان مخزَّنًا، بوسم أو دونه، يحميه Arkvory ويحمي كل طبقة يشير إليها. ويتخطاها الاحتفاظ بسبب المانع
reference. - نقل وسم أو حذفه لا يحرر شيئًا. تحتفظ ملفات البيان القديمة بطبقاتها إلى أن تحذف تلك الملفات بملخصاتها.
- بعد حذف ملف بيان بملخصه، يفقد مُخرَجه والطبقات التي لا يستخدمها ملف بيان آخر هذه الحماية. وتبقى مخزَّنة إلى أن يزيلها أحد بالاحتفاظ أو يحذفها كمُخرَجات. راجع التخزين.
- الطبقة التي دُفعت دون ملف بيان، مثل دفعة فشلت، غير محمية.
- عندما تُطلب مرة أخرى طبقة أُزيلت، يبلّغ السجل بأنها غير معروفة، ويرفعها الدفع التالي من جديد.
الأذونات
تحصل الرموز الشخصية ومفاتيح الملفات على وصول قراءة أو كتابة إلى مستودع. وتحصل مفاتيح الخدمة على إجراءات محددة.
| العملية | إجراءات مفتاح الخدمة | الرمز الشخصي أو مفتاح الملف |
|---|---|---|
| سحب ملفات البيان والطبقات | content.read | وصول القراءة |
| سرد الوسوم | artifact.list | وصول القراءة |
| الدفع | upload.create وupload.write وupload.complete | وصول الكتابة؛ ويحتاج الرمز إلى النطاق read-write |
| حذف وسم أو ملف بيان | artifact.delete | غير ممكن |
مفتاح CI الذي يدفع يسحب عادة أيضًا، مثل الصور الأساسية أو ذاكرة البناء المؤقتة. امنحه content.read وartifact.list كذلك. والمستودع غير الممنوح للمفتاح يجيب بـ 403 DENIED.
بوابات القراءة والمرايا
- بوابة القراءة تخدم عمليات السحب. ويحصل الدفع على
405. - المرآة تتلقى صور مصدرها مع وسومها وعمليات حذفها. ويسحب العملاء من المرآة على عنوانها الخاص. ويحصل الدفع على
409 DENIEDمع السببmirror_read_only.
الحدود
| الحد | القيمة |
|---|---|
| حجم ملف البيان | 4 MiB |
| حجم الطبقة | أكبر كائن في التثبيت، ARKVORY_MAX_OBJECT_BYTES (نحو 10 TiB افتراضيًا) |
| طلب رفع واحد | يجب أن ينتهي خلال 30 دقيقة، ويجب ألا يتوقف أكثر من 30 ثانية (ARKVORY_UPLOAD_DEADLINE_MS وARKVORY_UPLOAD_IDLE_TIMEOUT_MS). و30 دقيقة هي أيضًا أعلى قيمة مسموحة. |
| رفع غير مكتمل | يُزال مع بايتاته بعد 24 ساعة دون نشاط |
| مساحة القرص المؤقتة | حتى ضعف حجم الطبقة أثناء رفعها |
| عمليات الرفع المتزامنة | 1 لكل مفتاح و2 لكل خادم افتراضيًا (ARKVORY_MAX_UPLOADS_PER_PRINCIPAL وARKVORY_MAX_UPLOADS). ويستسلم الطلب المنتظر بعد 20 ثانية (ARKVORY_TRANSFER_QUEUE_TIMEOUT_MS). |
| عمليات التنزيل المتزامنة | 4 لكل مفتاح و16 لكل خادم افتراضيًا |
| الوسوم في الصفحة | 1000 |
| الحصة | تُحتسب الطبقات وملفات البيان وبايتات عمليات الرفع غير المكتملة ضمن حصة المستودع وسعة التثبيت |
يرسل Docker كل طبقة في طلب واحد. لذا يجب أن تصل الطبقة خلال مهلة الرفع، وعندما يفشل رفع طبقة يبدأ من البايت الأول. وللملفات التي يبلغ حجمها غيغابايتات كثيرة، استخدم arkvoryctl بدلًا من ذلك: فهو يرفع على أجزاء ويتابع بعد الفشل. وتوصف المتغيرات في متغيرات البيئة.
غير مدعوم
- واجهة Referrers API. وهي تجيب بالرمز
404، وتعود العملاء إلى الوسوم. - فهرس كل الصور،
/v2/_catalog. - ربط (mount) الطبقات من مستودع آخر. يرفع العميل الطبقة مرة أخرى.
- خدمة رموز لرموز Bearer. أرسل المفتاح نفسه بـ Basic أو Bearer.
- ذاكرة تخزين مؤقت تمريرية (pull-through cache) لـ Docker Hub أو لسجلات أخرى.
- ملفات البيان بالمخطط 1 في Docker، والملخصات غير
sha256. - حذف الطبقات منفردةً.
- قسم للصور في وحدة التحكم.
HTTP العادي للاختبار
يرفض Docker سجلًا دون HTTPS. وعناوين الحاسوب المحلي فقط (localhost و127.0.0.0/8) تعمل عبر HTTP العادي افتراضيًا. ولخادم اختبار على مضيف آخر، أضفه إلى insecure-registries في إعدادات خدمة Docker (/etc/docker/daemon.json على Linux) وأعد تشغيل Docker:
{
"insecure-registries": ["arkvory.test:8080"]
}يستخدم Podman الخيار --tls-verify=false. وعبر HTTP العادي ينتقل المفتاح كنص صريح. استخدم هذا في شبكة اختبار فقط.
أما الشهادة الصادرة عن جهة إصدار شهادات خاصة بك، فيقرأ Docker على Linux شهادة الجهة من /etc/docker/certs.d/<host>/ca.crt (مع المنفذ إن لم يكن 443). ويستخدم Docker Desktop مخزن الثقة في النظام.
استكشاف الأخطاء وإصلاحها
يطبع Docker رموز أخطاء السجل بأحرف صغيرة مع مسافات، مثل denied أو name invalid، متبوعة برسالة الخادم. ولكل خطأ أيضًا معرّف طلب في detail.requestId. أعطه لمسؤولك: فهو يعثر على الطلب في سجل الخادم.
| الخطأ | السبب | ما العمل |
|---|---|---|
UNAUTHORIZED (401) | المفتاح مفقود أو خاطئ أو منتهٍ أو مُبطَل | سجّل الدخول مرة أخرى بمفتاح صالح |
DENIED (403) | لا يستطيع المفتاح الكتابة أو لا يرى المستودع. والرمز ذو النطاق read يحصل على "Read-only personal access token". | استخدم مفتاحًا له وصول كتابة إلى هذا المستودع |
DENIED (409) | المستودع مرآة | ادفع إلى الخادم الرئيسي |
DENIED (507) | بلغت حصة المستودع أو سعة التثبيت حدها. وتُحتسب عمليات الرفع غير المكتملة أيضًا. | حرّر مساحة أو اطلب حصة أكبر |
NAME_INVALID | لا يحتوي المرجع على جزء الصورة بعد المستودع، أو فيه أحرف كبيرة | استخدم <host>/<repository>/<image>:<tag> بأحرف صغيرة |
MANIFEST_UNKNOWN | الوسم أو الملخص غير موجود في هذه الصورة | تحقق من الاسم بـ tags/list |
MANIFEST_BLOB_UNKNOWN | يشير ملف بيان إلى طبقة أو ملف بيان منصة غير موجود في هذا المستودع | ادفع الصورة كلها مرة أخرى ليرفع العميل الأجزاء الناقصة |
DIGEST_INVALID | البايتات لا تطابق الملخص | ادفع مرة أخرى. وإذا تكرر ذلك، فافحص الوكيل (proxy). |
TOOMANYREQUESTS (503 أو 429) | عمليات نقل كثيرة جدًا لهذا المفتاح في الوقت نفسه، أو الخادم مشغول | انتظر وأعد المحاولة. قلّل عمليات الرفع المتوازية للعميل، مثل "max-concurrent-uploads": 1 في إعدادات خدمة Docker، أو اطلب من المسؤول رفع حدود النقل. |
http: server gave HTTP response to HTTPS client | ليس للخادم HTTPS | أعدّ HTTPS، أو استخدم insecure-registries لخادم اختبار |
x509: certificate signed by unknown authority | لا يثق Docker بالشهادة | ثبّت شهادة جهة الإصدار (CA) كما هو موضح أعلاه |
413 Request Entity Too Large | يحدّ الوكيل العكسي حجم الطلب | اضبط client_max_body_size 0 في nginx |
| طبقة كبيرة تتوقف بعد 30 دقيقة | مهلة الرفع لطلب واحد | استخدم شبكة أسرع، أو أبقِ هذه الملفات خارج الصور وارفعها بـ arkvoryctl |