Compose: هل هناك طريقة لتأخير بدء تشغيل الحاوية لدعم الخدمات التابعة بوقت بدء تشغيل أطول

تم إنشاؤها على ٥ أغسطس ٢٠١٤  ·  314تعليقات  ·  مصدر: docker/compose

لدي حاوية MySQL تستغرق بعض الوقت لبدء التشغيل لأنها تحتاج إلى استيراد البيانات.

لدي حاوية Alfresco تعتمد على حاوية MySQL.

في الوقت الحالي ، عندما أستخدم التين ، تفشل خدمة Alfresco داخل حاوية Alfresco عندما تحاول الاتصال بحاوية MySQL ... ظاهريًا لأن خدمة MySQL لم تستمع بعد.

هل توجد طريقة للتعامل مع هذا النوع من المشكلات في الشكل؟

التعليق الأكثر فائدة

نعم ، سأكون مهتمًا بشيء كهذا - من المفترض أن أنشر عنه مسبقًا.

أصغر نمط تأثير يمكنني التفكير فيه والذي من شأنه إصلاح حالة الاستخدام هذه بالنسبة لنا هو ما يلي:

أضف "wait" كمفتاح جديد في fig.yml ، مع دلالات قيمة مماثلة للارتباط. سيعامل Docker هذا كشرط مسبق وانتظر حتى يتم خروج هذه الحاوية قبل المتابعة.

لذلك ، سيبدو ملف عامل الإرساء الخاص بي كما يلي:

db:
  image: tutum/mysql:5.6

initdb:
  build: /path/to/db
  link:
    - db:db
  command: /usr/local/bin/init_db

app:
  link:
    - db:db
  wait:
    - initdb

عند تشغيل التطبيق ، سيبدأ تشغيل جميع حاويات الارتباط ، ثم تشغيل حاوية الانتظار والتقدم فقط إلى حاوية التطبيق الفعلية بمجرد خروج حاوية الانتظار (initdb). يقوم initdb بتشغيل برنامج نصي ينتظر أن تكون قاعدة البيانات متاحة ، ثم يقوم بتشغيل أي عمليات تهيئة / عمليات ترحيل / أيا كان ، ثم الخروج.

هذه أفكاري ، على أي حال.

ال 314 كومينتر

في العمل ، نقوم بتغليف خدماتنا التابعة في نص برمجي يتحقق مما إذا كان الارتباط قد تم تشغيله بعد. أعلم أن أحد زملائي سيكون مهتمًا بهذا أيضًا! أنا شخصياً أشعر أنه من دواعي القلق على مستوى الحاوية انتظار توفر الخدمات ، لكن قد أكون مخطئًا :)

نفعل نفس الشيء مع التغليف. يمكنك رؤية مثال هنا: https://github.com/dominionenterprises/tol-api-php/blob/master/tests/provisioning/set-env.sh

سيكون من السهل أن يكون لديك برنامج نصي لنقطة الإدخال يعمل بشكل حلقات على جميع الروابط وينتظر حتى يعمل قبل بدء الأمر الذي يمر إليه.

يجب أن يتم تضمين هذا في Docker نفسه ، لكن الحل بعيد المنال. لا ينبغي اعتبار الحاوية قد بدأت حتى يتم فتح الرابط الذي تعرضه.

bfirsh هذا أكثر مما كنت

لا ينبغي اعتبار الحاوية قد بدأت حتى يتم فتح الرابط الذي تعرضه.

أعتقد أن هذا بالضبط ما يحتاجه الناس.

في الوقت الحالي ، سأستخدم صيغة مختلفة على https://github.com/aanand/docker-wait

نعم ، سأكون مهتمًا بشيء كهذا - من المفترض أن أنشر عنه مسبقًا.

أصغر نمط تأثير يمكنني التفكير فيه والذي من شأنه إصلاح حالة الاستخدام هذه بالنسبة لنا هو ما يلي:

أضف "wait" كمفتاح جديد في fig.yml ، مع دلالات قيمة مماثلة للارتباط. سيعامل Docker هذا كشرط مسبق وانتظر حتى يتم خروج هذه الحاوية قبل المتابعة.

لذلك ، سيبدو ملف عامل الإرساء الخاص بي كما يلي:

db:
  image: tutum/mysql:5.6

initdb:
  build: /path/to/db
  link:
    - db:db
  command: /usr/local/bin/init_db

app:
  link:
    - db:db
  wait:
    - initdb

عند تشغيل التطبيق ، سيبدأ تشغيل جميع حاويات الارتباط ، ثم تشغيل حاوية الانتظار والتقدم فقط إلى حاوية التطبيق الفعلية بمجرد خروج حاوية الانتظار (initdb). يقوم initdb بتشغيل برنامج نصي ينتظر أن تكون قاعدة البيانات متاحة ، ثم يقوم بتشغيل أي عمليات تهيئة / عمليات ترحيل / أيا كان ، ثم الخروج.

هذه أفكاري ، على أي حال.

(تمت المراجعة ، انظر أدناه)

+1 هنا أيضًا. ليس من الجاذبي القيام بذلك في الأوامر نفسها.

+1 كذلك. فقط واجهت هذه القضية. أداة رائعة راجع للشغل ، تجعل حياتي أسهل بكثير!

+1 سيكون رائعًا للحصول على هذا.

+1 أيضا. واجهت مؤخرا نفس مجموعة المشاكل

+1 أيضا. أي بيان من dockerguys؟

أنا أكتب نصوص مجمعة كنقاط دخول للمزامنة في الوقت الحالي ، ولست متأكدًا مما إذا كان وجود آلية في التين أمرًا حكيمًا إذا كان لديك أهداف أخرى للحاويات الخاصة بك والتي تقوم بالتزامن بطريقة مختلفة. يبدو تطبيقًا خاصًا جدًا بالنسبة لي ، مثل مسؤولية الحاويات التي تقوم بالعمل.

بعد بعض التفكير والتجريب ، أتفق مع هذا نوعًا ما.

على هذا النحو ، فإن التطبيق الذي أقوم ببنائه متزامن بشكل أساسي
waitfor (المضيف ، المنفذ) وظيفة تتيح لي انتظار خدمات التطبيق
يعتمد على (سواء تم اكتشافه عبر البيئة أو بشكل صريح
التكوين عبر خيارات CLI).

في صحتك
جوامع

جيمس ميلز / برولوجيك

البريد الإلكتروني: [email protected]
W: prologic.shortcircuit.net.au

يوم الجمعة ، 22 آب (أغسطس) 2014 الساعة 6:34 مساءً ، مارك ستيوارت إخطارات @github.com
كتب:

أنا أكتب نصوص مجمعة كنقاط دخول لمزامنتها في الوقت الحالي ،
لست متأكدًا مما إذا كان وجود آلية في الشكل أمرًا حكيمًا إذا كان لديك أهداف أخرى لـ
حاوياتك التي تقوم بالتزامن بطريقة مختلفة. يبدو جدا
تطبيق خاص بي على هذا النحو مسؤولية الحاويات
يقوم بالعمل.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/docker/fig/issues/374#issuecomment -53036154.

نعم بعض الأساسيات "تعتمد على" neeed هنا ...
لذلك إذا كان لديك 20 حاوية ، فلن تحتاج إلى تشغيل الشكل ويبدأ كل شيء بالترتيب الصحيح ...
ومع ذلك ، فإنه يحتوي أيضًا على بعض خيارات المهلة أو آليات التقاط الفشل الأخرى

+1 آخر هنا. لدي Postgres يستغرق وقتًا أطول من Django للبدء ، لذا فإن قاعدة البيانات ليست موجودة لأمر الترحيل بدون القرصنة.

ahknight مثير للاهتمام ، لماذا يتم تشغيل الترحيل خلال run ؟

ألا تريد بالفعل تشغيل الترحيل أثناء مرحلة build ؟ بهذه الطريقة يمكنك بدء تشغيل الصور الجديدة بشكل أسرع.

هناك برنامج نصي أكبر لبدء التشغيل للتطبيق المعني ، للأسف. في الوقت الحالي ، نقوم بعمل غير متعلق بقاعدة البيانات أولاً ، باستخدام nc -w 1 في حلقة لانتظار قاعدة البيانات ، ثم تنفيذ إجراءات قاعدة البيانات. إنه يعمل ، لكنه يجعلني أشعر بالقذارة (إيه).

لقد حققت الكثير من النجاح في القيام بهذا العمل خلال مرحلة fig build . لدي مثال واحد على ذلك مع مشروع django (لا يزال العمل قيد التقدم من خلاله): https://github.com/dnephin/readthedocs.org/blob/fig-demo/dockerfiles/database/Dockerfile#L21

لا حاجة لاقتراع لبدء التشغيل. على الرغم من أنني فعلت شيئًا مشابهًا مع mysql ، حيث كان عليّ إجراء استطلاع لبدء التشغيل لأن البرنامج النصي الأولي mysqld لم يكن يقوم بذلك بالفعل. يبدو أن البرنامج النصي الخاص بـ postgres هو أفضل بكثير.

هذا ما كنت أفكر فيه:

باستخدام فكرة docker / docker # 7445 يمكننا تنفيذ خاصية "wait_for_helth_check" في الشكل؟
إذن ستكون قضية تين وليس قضية عامل ميناء؟

هل هناك أي طريقة لجعل التين يتحقق من حالة برنامج التعاون الفني على الحاوية المرتبطة ، إذا كان الأمر كذلك ، فأعتقد أن هذا هو السبيل للذهاب. =)

dnephin ، هل يمكنك أن تشرح أكثر قليلاً ما تفعله في Dockerfiles للمساعدة في ذلك؟
أليست مرحلة البناء قادرة على التأثير على وقت التشغيل؟

docteurklein أستطيع. أصلحت الرابط أعلاه (https://github.com/dnephin/readthedocs.org/blob/fig-demo/dockerfiles/database/Dockerfile#L21)

الفكرة هي أن تقوم بكل عمليات "الإعداد" الأبطأ أثناء الإنشاء ، لذا لن تضطر إلى انتظار أي شيء أثناء بدء تشغيل الحاوية. في حالة وجود قاعدة بيانات أو فهرس بحث ، يمكنك:

  1. ابدأ الخدمة
  2. إنشاء المستخدمين وقواعد البيانات والجداول وبيانات التركيبات
  3. اغلاق الخدمة

كل ذلك كخطوة بناء واحدة. في وقت لاحق عندما تكون حاوية قاعدة البيانات fig up جاهزة للعمل بشكل أساسي على الفور ، ويمكنك أيضًا الاستفادة من ذاكرة التخزين المؤقت لإنشاء عامل الإرساء لهذه العمليات البطيئة.

لطيف! شكر :)

dnephin لطيف ، لم أفكر في ذلك.

+1 هذا مطلوب بالتأكيد.
قد يكون الاختراق القبيح لتأخير الوقت كافيًا في معظم الحالات ، ولكن سيكون الحل الحقيقي موضع ترحيب.

هل يمكنك إعطاء مثال على لماذا / عند الحاجة؟

في حالة الاستخدام لدي ، لدي خادم Elasticsearch ثم خادم تطبيق يتصل بـ Elasticsearch. يستغرق Elasticsearch بضع ثوانٍ لتدور ، لذلك لا يمكنني ببساطة عمل fig up -d لأن خادم التطبيق سيفشل على الفور عند الاتصال بخادم Elasticsearch.

لنفترض أن إحدى الحاوية تبدأ تشغيل MySQL والأخرى تبدأ تطبيقًا يحتاج إلى MySQL ويتضح أن التطبيق الآخر يبدأ بشكل أسرع. لدينا فشل عابر fig up بسبب ذلك.

crane لديه طريقة للتغلب على هذا من خلال السماح لك بإنشاء مجموعات يمكن أن تبدأ بشكل فردي. لذا يمكنك بدء مجموعة MySQL ، والانتظار لمدة 5 ثوانٍ ثم بدء الأشياء الأخرى التي تعتمد عليها.
يعمل على نطاق صغير ، لكن ليس حلاً حقيقيًا.

oskarhane لست متأكدًا مما إذا كان هذا "الانتظار 5 ثوانٍ"
كما سيتعين عليك القيام بذلك يدويًا في انتظار وتحميل المجموعة الأخرى ، وهذا نوع من الأعرج ، يجب أن يفعل التين ذلك من أجلك = /

oskarhane ، dacort ، dossot : ضع في اعتبارك أنه في العالم الحقيقي ، تتعطل الأشياء وتعيد تشغيلها ، وتذهب اتصالات الشبكة وتذهب ، وما إلى ذلك. سواء كان فيج يقدم راحة للانتظار على مقبس TCP أم لا ، يجب أن تكون حاوياتك مرن في حالات فشل الاتصال. بهذه الطريقة سيعملون بشكل صحيح في كل مكان.

أنت على حق ، ولكن حتى نصلح جميع التطبيقات الموجودة مسبقًا للقيام بأشياء مثل التعافي بأمان من عدم وجود مواردها الحيوية (مثل DB) عند البدء (وهو Great Thing ™ ولكن نادرًا ما تدعمه أطر العمل) ، يجب أن نستخدم fig start لبدء حاوية فردية بترتيب معين ، مع تأخيرات ، بدلاً من fig up .

أستطيع أن أرى برنامج شل النصي قادمًا للتحكم في الشكل للتحكم في عامل الإرساء: wink:

أنا بخير لأن هذا لم يتم تضمينه في الشكل ولكن بعض النصائح حول أفضل الممارسات لانتظار الاستعداد ستكون جيدة

رأيت في بعض التعليمات البرمجية المرتبطة من تعليق سابق تم ذلك:

while ! exec 6<>/dev/tcp/${MONGO_1_PORT_27017_TCP_ADDR}/${MONGO_1_PORT_27017_TCP_PORT}; do
    echo "$(date) - still trying to connect to mongo at ${TESTING_MONGO_URL}"
    sleep 1
done

في حالتي ، لا يوجد مسار /dev/tcp رغم ذلك ، فربما يكون توزيعة Linux مختلفة (؟) - أنا على Ubuntu

لقد وجدت بدلاً من ذلك هذه الطريقة التي يبدو أنها تعمل بشكل جيد:

until nc -z postgres 5432; do
    echo "$(date) - waiting for postgres..."
    sleep 1
done

يبدو أن هذا يعمل ولكني لا أعرف ما يكفي عن مثل هذه الأشياء لمعرفة ما إذا كانت قوية ... هل يعرف أي شخص ما إذا كانت هناك حالة سباق محتملة بين عرض المنفذ حتى nc وخادم postgres _ حقًا_ قادر على القبول أوامر؟

سأكون أكثر سعادة إذا كان من الممكن عكس الشيك - بدلاً من الاقتراع من الحاويات التابعة ، هل من الممكن بدلاً من ذلك إرسال إشارة من حاوية الهدف (أي خادم postgres) إلى جميع المعالين؟

ربما تكون فكرة سخيفة ، هل لدى أحد أي أفكار؟

تعد روابط أحادية الاتجاه ، لذا فإن الاستقصاء من حاوية المصب هو الطريقة الوحيدة حاليًا للقيام بذلك.

هل يعرف أي شخص ما إذا كان هناك حالة سباق محتملة بين ظهور المنفذ لخادم nc و postgres قادر حقًا على قبول الأوامر؟

لا توجد طريقة لمعرفة الحالة العامة - قد يكون هذا صحيحًا بالنسبة إلى postgres ، وقد يكون خطأ بالنسبة للخدمات الأخرى - وهي حجة أخرى لعدم القيام بذلك في الشكل.

aanand لقد حاولت استخدام نهج عامل

كنت آمل ألا أرى هذا الخطأ بربط حاوية الانتظار بـ Orientdb. لكن لسوء الحظ ما زلت أحصل عليه بشكل عشوائي. هذا هو الإعداد الخاص بي (Docker version 1.4.1، fig 1.0.1 on an Ubuntu 14.04 Box):

orientdb:
    build: ./Docker/orientdb
    ports:
        -   "2424:2424"
        -   "2480:2480"
wait:
    build: ./Docker/wait
    links:
        - orientdb:orientdb
....
core:
    build:  ./Docker/core
    ports:
        -   "3000:3000"
    links:
        -   orientdb:orientdb
        -   nsqd:nsqd

هو موضع تقدير أي مساعدة. شكر.

mindnuts الصورة wait هي أكثر من مجرد عرض توضيحي ؛ انها ليست مناسبة للاستخدام في fig.yml . يجب عليك استخدام نفس الأسلوب (الاقتراع المتكرر) في حاوية core الخاصة بك لانتظار بدء الحاوية orientdb قبل بدء العملية الرئيسية.

بدأ +1 للتو في الوصول إلى هذا لأنني أقوم بسحب الصور المبنية المخصصة مقابل بنائها في fig.yml. فشل تطبيق العقدة لأن mongodb ليس جاهزًا بعد ...

لقد أمضيت للتو ساعات في تصحيح أخطاء سبب إمكانية الوصول إلى MySQL عند بدء تشغيل WordPress يدويًا باستخدام Docker ، ولماذا كان غير متصل بالإنترنت عند البدء في الشكل. الآن فقط أدركت أن Fig يعيد دائمًا تشغيل حاوية MySQL كلما بدأت التطبيق ، لذلك تموت نقطة دخول WordPress.sh عدم القدرة بعد على الاتصال بـ MySQL.

لقد أضفت نقطة الإدخال التي تم تجاوزها الخاصة بي والتي تنتظر لمدة 5 ثوانٍ قبل تنفيذ نقطة الدخول الحقيقية. ولكن من الواضح أن هذه حالة استخدام تحتاج إلى حل عام ، إذا كان من المفترض أن يكون من السهل تشغيل حاوية MySQL + WordPress مع Docker / Fig.

لذلك تموت نقطة دخول WordPress.sh غير قادرة بعد على الاتصال بـ MySQL.

أعتقد أن هذه مشكلة في حاوية WordPress.

بينما كنت في البداية من المعجبين بهذه الفكرة ، بعد قراءة https://github.com/docker/docker/issues/7445#issuecomment -56391294 ، أعتقد أن هذه الميزة ستكون نهجًا خاطئًا ، وتشجع بالفعل الممارسات السيئة.

يبدو أن هناك حالتين تهدف هذه القضية إلى معالجتهما:

يجب أن تكون خدمة التبعية متاحة لإجراء بعض التهيئة.

يجب أن تتم أي تهيئة للحاوية بالفعل خلال build . بهذه الطريقة يتم تخزينها مؤقتًا ، ولا يلزم تكرار العمل بواسطة كل مستخدم للصورة.

يجب أن تكون خدمة التبعية متاحة حتى يمكن فتح اتصال

يجب أن يكون التطبيق مرنًا حقًا لفشل الاتصال وإعادة محاولة الاتصال.

أفترض أن جذر المشكلة هو أنه لا توجد قواعد أساسية بشأن من تقع مسؤوليته على انتظار أن تصبح الخدمات جاهزة. ولكن حتى لو كان الأمر كذلك ، أعتقد أنه من غير الواقعي بعض الشيء توقع قيام المطورين بإضافة اتصال قاعدة البيانات لإعادة المحاولة إلى كل برنامج نصي للتهيئة. غالبًا ما تكون هناك حاجة إلى مثل هذه البرامج النصية لإعداد وحدات تخزين بيانات فارغة تم تركيبها للتو (مثل إنشاء قاعدة البيانات).

ستكون المشكلة في الواقع أقل اقتحامية إذا لم يقم Figur بإعادة تشغيل الحاويات المرتبطة (أي خادم قاعدة البيانات) عند إعادة تشغيل حاوية التطبيق. لا أعرف حقًا لماذا يفعل ذلك.

ستكون المشكلة في الواقع أقل اقتحامية إذا لم يقم Figur بإعادة تشغيل الحاويات المرتبطة (أي خادم قاعدة البيانات) عند إعادة تشغيل حاوية التطبيق. لا أعرف حقًا لماذا يفعل ذلك.

في الواقع ، لا يقتصر الأمر على _ إعادة تشغيل_ الحاويات ، بل _إخراجها وإعادة إنشائها_لأنها أبسط طريقة للتأكد من التقاط التغييرات التي تم إجراؤها على fig.yml . يجب أن ننفذ في النهاية حلاً أكثر ذكاءً يمكنه مقارنة "التكوين الحالي" بـ "التكوين المطلوب" وإعادة إنشاء ما تغير فقط.

بالعودة إلى المشكلة الأصلية ، لا أعتقد حقًا أنه من غير الواقعي توقع أن يكون للحاويات منطق إعادة محاولة الاتصال - إنه أمر أساسي لتصميم نظام موزع يعمل. إذا احتاجت برامج نصية مختلفة إلى مشاركتها ، فيجب تضمينها في ملف قابل للتنفيذ (أو وحدة خاصة باللغة إذا كنت لا تستخدم shell) ، بحيث يمكن لكل نص برمجي استدعاء waitfor db في الأعلى.

@ kennu ماذا عن --no-recreate ؟ / ccaanand

aanand قصدت التعليق غير الواقعي من وجهة نظر Docker Hub مليء بالفعل بالصور المنشورة التي ربما لا تتعامل مع إعادة محاولة الاتصال في نصوص التهيئة الخاصة بهم ، وسيكون من التعهد أن يقوم الجميع بإضافتها. لكن أعتقد أنه يمكن القيام بذلك إذا نشرت Docker Inc نوعًا من الإرشادات / المتطلبات الرسمية.

أنا شخصياً أفضل إبقاء الحاويات / الصور بسيطة على الرغم من السماح للنظام الأساسي بالقلق بشأن حل التبعيات. في الواقع ، قد تحل سياسة إعادة تشغيل Docker بالفعل كل شيء (إذا فشلت حاوية التطبيق في الاتصال بقاعدة البيانات ، فسيتم إعادة تشغيلها والمحاولة مرة أخرى حتى تصبح قاعدة البيانات متاحة).

لكن الاعتماد على سياسة إعادة التشغيل يعني أنه يجب تمكينها افتراضيًا ، وإلا يقضي الأشخاص ساعات في تصحيح المشكلة (كما فعلت للتو). على سبيل المثال ، يتم تعيين Kubernetes افتراضيًا على RestartPolicyAlways لبودات.

أي تقدم في هذا؟ أود أن أكرر أن توقع تغيير جميع صور عامل الإرساء وأن يقوم المجتمع بأكمله بتنفيذ ممارسات إعادة محاولة الاتصال أمر غير معقول. Fig هي أداة تنسيق Docker وتكمن المشكلة في الترتيب الذي تقوم به الأشياء ، لذا يجب إجراء التغيير في Fig ، وليس Docker أو المجتمع.

من غير المعقول توقع تغيير جميع صور عامل الإرساء وتنفيذ المجتمع بأكمله لممارسات إعادة محاولة الاتصال

لا يعني ذلك أن التطبيق يجب أن يعيد المحاولة بسبب عامل الإرساء أو التين. يجب أن تكون التطبيقات مرنة في حالة انقطاع الاتصالات لأن الشبكة غير موثوقة . يجب إنشاء أي تطبيق بهذه الطريقة بالفعل.

أنا شخصياً لم أضطر إلى تنفيذ عمليات إعادة المحاولة في أي من حاوياتي ، كما أنني لم أكن بحاجة إلى أي تأخير أو انتظار عند بدء التشغيل. أعتقد أن معظم حالات هذه المشكلة تندرج في هاتين الفئتين (ربما لا يكون استخدامي لـ "إعادة المحاولة" رائعًا هنا ، فأنا أعني أكثر أنه سيعيد إنشاء اتصال إذا تم إغلاق الاتصال ، وليس بالضرورة إجراء استطلاع لبعض الفترة عند محاولة إجراء عدة مرات).

إذا تأكدت من أن جميع عمليات التهيئة تحدث أثناء مرحلة "الإنشاء" ، وأنه تمت إعادة إنشاء الاتصالات في الطلب التالي ، فلن تحتاج إلى إعادة المحاولة (أو الانتظار على الحاويات الأخرى للبدء). إذا تم فتح الاتصالات ببطء (عند تقديم الطلب الأول) ، فبدلاً من ذلك بفارغ الصبر (أثناء بدء التشغيل) ، أظن أنك لن تحتاج إلى إعادة المحاولة على الإطلاق.

تكمن المشكلة في ترتيب عمل [الشكل]

لا أرى أي ذكر لذلك في هذه المناقشة حتى الآن. يبدأ تشغيل أوامر التين بناءً على الروابط المحددة في التكوين ، لذلك يجب دائمًا بدء تشغيل الحاويات بالترتيب الصحيح. هل يمكنك تقديم حالة اختبار يكون الطلب فيها غير صحيح؟

يجب أن أتفق مع dnephin هنا. بالتأكيد ، سيكون من الملائم أن يكون التركيب / التين قادرًا على القيام ببعض السحر والتحقق من توفر الخدمات ، ومع ذلك ، ماذا سيكون السلوك المتوقع إذا لم تستجب الخدمة؟ هذا _ حقًا_ يعتمد على متطلبات التطبيق / المكدس الخاص بك. في بعض الحالات ، يجب تدمير المكدس بالكامل واستبداله بآخر جديد ، وفي حالات أخرى يجب استخدام مكدس تجاوز الفشل. يمكن التفكير في العديد من السيناريوهات الأخرى.

لا يمكن للتكوين / الشكل اتخاذ هذه القرارات ، ويجب أن تكون خدمات المراقبة من مسؤولية التطبيقات التي تعمل داخل الحاوية.

أود أن أقترح أن dnephin كان مجرد محظوظ. إذا قمت بتقسيم عمليتين متوازيتين ، ستتصل إحداهما بمنفذ يستمع إليه الآخر ، فأنت تقدم أساسًا حالة سباق ؛ يانصيب لمعرفة العملية التي تتم للتهيئة بشكل أسرع.

أود أيضًا أن أكرر مثال تهيئة WordPress: فهو يقوم بتشغيل برنامج نصي لبدء التشغيل يقوم بإنشاء قاعدة بيانات جديدة إذا لم تكن حاوية MySQL تحتوي عليها بعد (لا يمكن القيام بذلك عند إنشاء صورة Docker ، نظرًا لأنها تعتمد على حجم البيانات المركب خارجيًا). يصبح مثل هذا البرنامج النصي أكثر تعقيدًا بشكل ملحوظ إذا كان عليه التمييز بين أخطاء قاعدة البيانات العامة وأخطاء "قاعدة البيانات ليست جاهزة بعد" وتنفيذ بعض منطق إعادة المحاولة العقلاني داخل البرنامج النصي shell. أعتبر أنه من المحتمل جدًا أن مؤلف الصورة لن يختبر فعليًا نص بدء التشغيل مقابل حالة السباق المذكورة.

ومع ذلك ، توفر سياسة إعادة التشغيل المضمنة في Docker حلاً بديلاً لهذا ، إذا كنت مستعدًا لقبول فشل الحاويات بشكل متقطع في البدء وطباعة الأخطاء بانتظام في السجلات. (وإذا كنت تتذكر تشغيله.)

شخصيًا ، سأجعل الأشياء تعمل فقط ، من خلال الكشف التلقائي عن منافذ الحاوية التي تتعرض لحاوية مرتبطة ، قم باختبار اتصالها قبل بدء الحاوية المرتبطة (مع مهلة معقولة) ، وفي النهاية توفير إعداد تكوين لتجاوز / تعطيل هذه الوظيفة.

لا يمكن القيام بذلك عند إنشاء صورة Docker ، نظرًا لأنها تعتمد على حجم البيانات المركب خارجيًا

صحيح. تتمثل الطريقة هنا في بدء حاوية قاعدة البيانات مرة واحدة فقط (إذا لزم الأمر ، بنقطة إدخال / أمر مختلف) ، لتهيئة قاعدة البيانات ، أو استخدام حاوية البيانات فقط لقاعدة البيانات ، التي تم إنشاؤها من نفس الصورة مثل حاوية قاعدة البيانات نفسها.

يصبح مثل هذا البرنامج النصي أكثر تعقيدًا بشكل ملحوظ إذا كان عليه التمييز بين أخطاء قاعدة البيانات العامة وأخطاء "قاعدة البيانات ليست جاهزة بعد"

سيواجه تكوين / التين نفس المشكلة هناك ؛ كيف تتحقق مما إذا كانت MySQL تعمل أم لا ، وتقبل الاتصالات؟ (و PostgreSQL و (_ أدخل خدمتك هنا_)). أيضًا ، من أين_ يجب تنفيذ "ping" من؟ داخل الحاوية التي تبدأها ، من المضيف؟

بقدر ما أستطيع أن أقول ، تتضمن صورة WordPress الرسمية فحصًا لمعرفة ما إذا كانت MySQL تقبل الاتصالات في docker-entrypoint.sh

thaJeztah "أضف بعض منطق إعادة المحاولة البسيط في PHP لأخطاء اتصال MySQL" من تأليف tianon منذ يومين - نيس. :-) من يدري ، ربما سيصبح هذا نهجًا قياسيًا بعد كل شيء ، لكن لا يزال لدي شكوك ، خاصة حول هذا النوع من عمليات إعادة المحاولة التي تم اختبارها بالفعل من قبل جميع مؤلفي الصور.

حول pinging المنفذ - لا أستطيع أن أقول مرتجلاً ما سيكون التنفيذ الأمثل. أعتقد أنه ربما يكون التحقق من الاتصال بسيطًا من حاوية مرتبطة مؤقتة وإعادة المحاولة أثناء الحصول على ECONNREFUSED. مهما كان ما يحل 80٪ (أو ربما 99٪) من المشكلات ، فلا يتعين على المستخدمين حلها بأنفسهم مرارًا وتكرارًا في كل مرة.

@ كينو آه! شكرًا ، لم أكن على علم بأنه تمت إضافته مؤخرًا ، فقط تحقق من النص الآن بسبب هذه المناقشة.

لأكون واضحًا ، أفهم المشكلات التي تواجهها ، لكنني لست متأكدًا من أن Compose / Fig سيكون قادرًا على حلها بطريقة نظيفة تناسب الجميع (وبشكل موثوق). أتفهم أن العديد من الصور الموجودة في السجل لا تحتوي على "ضمانات" للتعامل مع هذه المشكلات ، لكنني أشك في أنها مسؤولية Compose / Fig لإصلاح ذلك.

بعد ما ذكر أعلاه ؛ أعتقد أنه سيكون من الجيد توثيق ذلك في قسم أفضل ممارسات Dockerfile .

يجب أن يكون الناس على علم بهذا ويجب إضافة بعض الأمثلة لتوضيح كيفية التعامل مع "انقطاع" الخدمة. بما في ذلك رابط لمقال WikiPedia الذي ذكره

واجهت نفس المشكلة وأعجبني بهذه الفكرة من

Personally, I would make Things Just Work, by making Fig autodetect which container ports are exposed to a linked container, ping them before starting the linked container (with a sane timeout), and ultimately provide a configuration setting to override/disable this functionality.

أعتقد أن هذا من شأنه أن يحل الكثير من حالات الاستخدام النموذجية ، كما هو الحال بالنسبة لي عند الاعتماد على حاوية mongodb الرسمية.

أنا أتفق معsoupdiver. أواجه أيضًا مشكلة فيما يتعلق بحاوية mongo ، وعلى الرغم من أنني أعمل مع برنامج نصي start.sh ، إلا أن النص ليس ديناميكيًا ويضيف ملفًا آخر أحتاج إلى الاحتفاظ به في الريبو الخاص بي (أود فقط الحصول على ملف Dockerfile و docker-compose.yml في my node repo). سيكون من الجيد لو كانت هناك طريقة ما لجعلها تعمل فقط ، لكنني أعتقد أن شيئًا بسيطًا مثل مؤقت الانتظار لن يقطعه في معظم الحالات.

لا يكفي اختبار اتصال IMO ، لأن اتصال الشبكة الأساسي قد يكون متاحًا ، لكن الخدمة نفسها لا تزال غير جاهزة.
هذا هو الحال مع صورة MySQL على سبيل المثال ، فإن استخدام curl أو telnet لفحص الاتصال على المنافذ المكشوفة سيكون أكثر أمانًا ، على الرغم من أنني لا أعرف ما إذا كان ذلك سيكون كافيًا. لكن معظم الحاويات لا تحتوي على هذه الأدوات مثبتة بشكل افتراضي.

يمكن عامل ميناء أو التين التعامل مع هذه الشيكات؟

يمكن عامل ميناء أو التين التعامل مع هذه الشيكات؟

باختصار: _ no_. لأسباب مختلفة؛

  • إجراء "ping" من داخل حاوية يعني تشغيل عملية ثانية. لا يمكن لـ Fig / Compose بدء هذه العملية تلقائيًا ، ولا أعتقد أنك تريد أن يقوم Fig / Compose بتعديل الحاوية الخاصة بك عن طريق تثبيت برنامج (مثل curl أو telnet) فيه.
  • (كما ذكرت في تعليق سابق) ، تتطلب كل خدمة طريقة مختلفة للتحقق مما إذا كانت تقبل الاتصالات / جاهزة للاستخدام. قد تحتاج بعض الخدمات إلى بيانات اعتماد أو شهادات لتأسيس اتصال. لا يمكن لـ Fig / Compose اختراع كيفية القيام بذلك تلقائيًا.

ولا أعتقد أنك تريد أن يقوم Fig / Compose بتعديل الحاوية الخاصة بك عن طريق تثبيت برنامج (مثل curl أو telnet) فيه.

لا ، بالتأكيد لا.

لا يمكن لـ Fig / Compose اختراع كيفية القيام بذلك تلقائيًا.

لا يخترع. كنت أفكر أكثر في تعليمات التين أو عامل الرصيف ، وكيفية التحقق منه ، على سبيل المثال.

web:
    image: nginx
    link: db
db:
   is_available: "curl DB_TCP_ADDR:DB_TCP_PORT"

سيتم تنفيذ الأمر telnet على مضيف عامل الإرساء ، وليس في الحاوية.
لكني أفكر بصوت عالٍ ، أعلم أن هذا ليس الحل الأمثل. ولكن يمكن تحسين الطريقة الحالية لاستخدام نصوص التحقق المخصصة للحاويات.

سيتم تنفيذ الأمر telnet على مضيف عامل الإرساء ، وليس في الحاوية.

ثم يجب تثبيت curl أو <name a tool that's needed> على المضيف. قد يكون لهذا الأمر مشكلات أمنية ضخمة (على سبيل المثال ، يريد شخص ما أن يكون مضحكًا ويستخدم is_available: "rm -rf /" ). بصرف النظر عن ذلك ، فإن القدرة على الوصول إلى قاعدة البيانات من _ المضيف_ لا تضمن إمكانية الوصول إليها أيضًا من داخل الحاوية.

لكني أفكر بصوت عالٍ ، ...

أنا أعلم ، وأنا أقدر ذلك. اعتقد فقط أنه لا توجد طريقة موثوقة لأتمتة هذا ، أو قد يخدم معظم حالات الاستخدام. في كثير من الحالات ، قد ينتهي بك الأمر بشيء معقد (خذ ، على سبيل المثال ، مثال curl ؛ كم من الوقت يجب أن يحاول الاتصال؟ أعد المحاولة؟). من الأفضل نقل هذا التعقيد داخل الحاوية ، وهو ما سيكون مفيدًا أيضًا إذا تم تشغيل الحاوية باستخدام Docker ، وليس باستخدام Fig / Compose.

thaJeztah أتفق معك تمامًا. ومن المحتمل جدًا أنه لن يكون هناك حل بنسبة 100٪.

سأكرر اقتراحًا قدمته سابقًا: سيكون كافياً بالنسبة لي إذا كان بإمكاني أن أذكر في التين .yml "انتظر حتى تخرج هذه الحاوية قبل تشغيل هذه الحاوية الأخرى".

سيسمح لي هذا بصياغة حاوية تعرف كيفية انتظار كل تبعياتها - تحقق من المنافذ ، وتهيئة قواعد البيانات ، وما إلى ذلك - وستتطلب معرفة التين بأقل قدر ممكن.

أرى أنه تم تكوينه على أنه شيء مثل:

"" "
تطبيق:
الروابط:
- ديسيبل: ديسيبل
المتطلبات:
- الركض أولا

runthisfirst:
الروابط:
- ديسيبل: ديسيبل
"" "

يحتوي runthisfirst على رابط يعني بدء تشغيل قاعدة البيانات حتى تتمكن من التحقق من الوصول. سيتم تشغيل التطبيق فقط بمجرد خروج runthisfirst (نقاط المكافأة إذا كان يجب الخروج من runthisfirst بنجاح).

هل هذا ممكن كإجابة؟

KJL

في 10 فبراير 2015 ، في الساعة 05:28 ، كتب Tobias Munk [email protected] :

thaJeztah https://github.com/thaJeztah أتفق معك تمامًا. ومن المحتمل جدًا أنه لن يكون هناك حل بنسبة 100٪.

-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub https://github.com/docker/fig/issues/374#issuecomment -73561930.

لقد حاولت للتو ترحيل مشغلات البرامج النصية الخاصة بي وواجهت هذه المشكلة. سيكون من الجيد إضافة مفتاح نوم / انتظار بسيط ينام فقط لهذا العدد من الثواني قبل تشغيل الحاوية التالية.

db:
  image: tutum/mysql:5.6
  sleep: 10
app:
  link:
    - db:db

أنا حقا لا أحب هذا لعدد من الأسباب.

أ) أعتقد أنه المكان الخطأ لذلك
ب) كم من الوقت تنام؟
ج) ماذا لو لم تكن المهلة طويلة بما يكفي؟

بصرف النظر عن القضايا الواضحة التي لا أعتقدها حقًا
يجب أن تهتم البنية التحتية لما التطبيق
هو والعكس صحيح. IHMO يجب كتابة التطبيق ليكون
أكثر تسامحًا و / أو ذكاءً بشأن متطلباتها الخاصة.

يقال أن التطبيقات الحالية والتطبيقات القديمة
سيحتاج شيئًا - لكن ربما يجب أن يكون أكثر
سطور:

أ docker-compose.yml :

db:
  image: tutum/mysql:5.6
app:
  wait: db
  link:
    - db:db

حيث ينتظر wait الخدمات "المكشوفة" على db لتصبح متاحة.

المشكلة كيف تحدد ذلك؟

في أبسط الحالات ، تنتظر حتى تتمكن من فتح ملفات
اتصال tcp أو udp بالخدمات المكشوفة.

قد يكون هذا مبالغة في التعامل مع هذه المشكلة ، ولكن ما سيكون حلاً جيدًا هو إذا قدم عامل الإرساء نظامًا لتشغيل الحدث حيث يمكنك بدء تشغيل مشغل من حاوية ما أدى إلى نوع من رد الاتصال في حاوية أخرى. في حالة انتظار استيراد البيانات إلى قاعدة بيانات MySQL قبل بدء خدمة أخرى ، فإن مجرد مراقبة ما إذا كان المنفذ متاحًا ليس كافيًا.

إن وجود برنامج نصي لنقطة الدخول يضبط تنبيهًا لـ Docker من داخل الحاوية (قم بتعيين متغير بيئة محدد مسبقًا على سبيل المثال) والذي أدى إلى تشغيل حدث في حاوية أخرى (ربما تعيين متغير البيئة المتزامن نفسه) من شأنه تمكين البرامج النصية على كلا الجانبين لمعرفة متى المهام كاملة.

بالطبع يمكننا إعداد خادم مقبس خاص بنا أو وسائل أخرى ، لكن هذا أمر شاق لحل مشكلة تنسيق الحاوية.

aanand أنا _ تقريبًا_ لدي شيء يعمل باستخدام نهج الانتظار الخاص بك كنقطة انطلاق. ومع ذلك ، هناك شيء آخر يحدث بين تشغيل عامل الإرساء وتشغيل عامل الإرساء حيث يبدو أن الأول معلق بينما يعمل الأخير بشكل ساحر.

مثال docker-compose.yml:

db:
  image: postgres
  ports:
    - "5432"
es:
  image: dockerfile/elasticsearch
  ports:
    - "9200"
wait:
  image: n3llyb0y/wait
  environment:
    PORTS: "5432 9200"
  links:
    - es
    - db

ثم باستخدام ...

docker-compose run wait

لكن هذا لا يجب أن يكون. تبدأ الخدمات المرتبطة ويبدو أننا على وشك الانتظار حتى تختنق فقط (على الأقل في بيئة Virtualbox الخاصة بي. وصلت إلى الحلقة nc وحصلنا على نقطة واحدة ثم ... لا شيء).

ومع ذلك ، مع تشغيل الخدمات المرتبطة يمكنني استخدام هذه الطريقة (وهو ما كنت أفعله في الأساس لبناءات CI الخاصة بنا)

docker run -e PORTS="5432 9200" --links service_db_1:wait1 --links service_es_1:wait2 n3llyb0y/wait

يبدو أن docker-compose run يجب أن يعمل بنفس الطريقة. الفرق هو أنه عند استخدام docker-compose run مع علامة الفصل -d لن تحصل على فائدة انتظار كخلفيات حاوية الانتظار وأعتقد (في هذه اللحظة) أن عدم استخدام العلم يتسبب في الانتظار لخنق الخدمات الأخرى غير الخلفية. سوف ألقي نظرة فاحصة

بعد قليل من التجربة والخطأ ، يبدو أن النهج أعلاه يعمل! إنها مجرد قاعدة Busbox لا تحتوي على استخدام netcat الذي يعمل جيدًا. يعمل الإصدار المُعدّل من aanand الأداة المساعدة للانتظار ضد docker-compose run <util label> بدلاً من docker-compose up . مثال على الاستخدام في الارتباط.

لست متأكدًا مما إذا كان يمكنه التعامل مع مواقف التسلسل وفقًا للسؤال الأصلي. على الاغلب لا.

اسمحوا لي أن أعرف ما هو رأيك.

هذه قضية مثيرة جدا للاهتمام. أعتقد أنه سيكون من المثير للاهتمام حقًا أن يكون لديك طريقة تنتظر بها إحدى الحاويات حتى تصبح أخرى جاهزة. ولكن كما يقول الجميع ، ماذا يعني الاستعداد؟ في حالتي ، لدي حاوية لـ MySQL ، حاوية أخرى تدير النسخ الاحتياطية وهي أيضًا مسؤولة عن استيراد قاعدة بيانات أولية ، ثم حاويات كل تطبيق يحتاج إلى قاعدة البيانات. من الواضح أن انتظار تعرض المنافذ لا يكفي. أولاً ، يجب بدء تشغيل حاوية mysql ثم الانتظار حتى تصبح خدمة mysql جاهزة للاستخدام ، وليس قبل ذلك. للحصول على ذلك ، كنت بحاجة إلى تنفيذ برنامج نصي بسيط ليتم تنفيذه عند إعادة التشغيل الذي يستخدم وظيفة docker exec . في الأساس ، سيكون الرمز الزائف مثل:

run mysql
waitUntil "docker exec -t mysql mysql -u root -prootpass database -e \"show tables\""
run mysql-backup
waitUntil "docker exec -t mysql mysql -u root -prootpass database -e \"describe my_table\""
run web1
waitUntil "dexec web1 curl localhost:9000 | grep '<h1>Home</h1>'"
run web2
waitUntil "dexec web2 curl localhost:9000 | grep '<h1>Home</h1>'"
run nginx

حيث تحتوي الوظيفة waitUntil على حلقة بها انقضاء مهلة تحلل الأمر docker exec … وتحقق مما إذا كان كود الخروج هو 0.

مع ذلك أؤكد أن كل حاوية تنتظر حتى تصبح تبعياتها جاهزة للاستخدام.

لذلك أعتقد أنه يمكن أن يكون خيارًا للتكامل مع أداة إنشاء. ربما شيء من هذا القبيل ، حيث يعلن wait_until قائمة من التبعيات الأخرى (الحاويات) وينتظر كل واحد حتى يستجيب جيدًا للأمر المقابل (أو ربما بنمط اختياري أو تعبير عادي للتحقق مما إذا كانت النتيجة تطابق شيء تتوقعه ، على الرغم من أن استخدام الأمر grep قد يكون كافيًا).

mysql:
  image: mysql
  ...
mysql-backup:
  links:
   - mysql
  wait_until:
   - mysql: mysql -u root -prootpass database -e "show tables"
  ...
web1:
  links:
   - mysql
  wait_until:
   - mysql: mysql -u root -prootpass database -e "describe my_table"
  ...
web2:
  links:
   - mysql
  wait_until:
   - mysql: mysql -u root -prootpass database -e "describe my_table"
  ...
nginx:
  links:
   - web1
   - web2
  wait_until:
   - web1: curl localhost:9000 | grep '<h1>Home</h1>'
   - web2: curl localhost:9000 | grep '<h1>Home</h1>'
  ...

مَا أَيّتْ بَسِطَةً لِمِنْفَاءٍ مَثَلْ؟
http://docs.azk.io/en/azkfilejs/wait.html#

robsonpeixoto : انتظار المنفذ لا يكفي لكثير من حالات الاستخدام. على سبيل المثال ، لنفترض أنك تزرع قاعدة بيانات ببيانات عند الإنشاء ولا تريد أن يبدأ خادم الويب ويتصل بها حتى تكتمل عملية البيانات. سيتم فتح المنفذ طوال الوقت حتى لا يمنع خادم الويب من البدء.

شيء مثل WaitCondition الخاص بـ AWS CloudFormation سيكون رائعًا. http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-waitcondition.html

+1 أواجه نفس المشكلة عند استخدام Docker لاختبار تطبيقاتي Rails التي تعتمد على MySQL

+1 لدي هذه المشكلة أيضًا. تعجبني فكرة

+1

لقد فتحت علامة التبويب هذه لفترة من الوقت: http://crosbymichael.com/docker-events.html ... تبدو ذات صلة

+1

+1 لمهلة بسيطة

+1 لحالة جاهزة

+1

أنا أقوم بحل هذا بشكل موثوق للغاية على مستوى التطبيق منذ فترة ، كما هو موصى به في هذا الموضوع.

فقط لإعطائك فكرة عن كيفية تنفيذ ذلك على MySQL + PHP ، إليك الكود الخاص بي.

من igorw / أعد المحاولة :)

نظرًا لأن الشبكة موثوقة ، يجب أن تعمل الأشياء دائمًا. هل انا على حق؟ لتلك الحالات عندما لا يفعلون ، هناك إعادة المحاولة.

+1

@ schmunk42 أشياء لطيفة - يعجبني أنها مثال جيد على كل من إنشاء الاتصال وإجراء عملية إعداد قاعدة بيانات مثالية.

قد يكون من الجيد إنشاء (بعض) الأمثلة الأساسية لتضمينها في المستندات ، لحالات مختلفة ، مثل NodeJS و Ruby و PHP.

+1 ، على الأقل يجب أن يوفر بعض الخيارات لإضافة بعض التأخير قبل بدء الحاوية بنجاح.

+1

كيفية حل المشكلات عند محاولة الاتصال بخدمات ليست رمزك.
على سبيل المثال ، إذا كان لديك الخدمة Service وقاعدة البيانات InfluxDB . Services يتطلب InfluxDB و InfluxDB لديه بدء تشغيل بطيء.

كيف يمكن لرسالة الميناء الانتظار للحصول على InfluxDB جاهزة؟

أنا الرمز الخاص بي ، يمكنني حله عن طريق إعادة المحاولة. لكن بالنسبة للتطبيق الثالث ، لا يمكنني تغيير الرمز.

robsonpeixoto هناك بعض الأمثلة في هذه التذكرة باستخدام netcat أو طرق مشابهة. يمكنك إلقاء نظرة على مثال MySQL في بطاقة أخرى: https://github.com/docker/docker/issues/7445#issuecomment -101523662

هذا هو السبب في أنني أعتقد أن كل حاوية يجب أن يكون لديها القدرة الاختيارية للإشارة إلى استعدادها الخاص. بالنسبة إلى قاعدة بيانات ، على سبيل المثال ، أريد الانتظار حتى تصبح الخدمة جاهزة تمامًا ، وليس عند إنشاء العملية. لقد قمت بحل هذا باستخدام شيكات مخصصة docker exec والتحقق مما إذا كان بإمكانه حل استعلام بسيط ، على سبيل المثال.

بعض العلامات الاختيارية لـ docker run للإشارة إلى أمر فحص داخلي سيكون رائعًا لربطه لاحقًا من حاوية أخرى باستخدام علامة خاصة للرابط.

شيء مثل:

$ sudo docker run -d --name db training/postgres --readiness-check /bin/sh -c "is_ready.sh"
$ sudo docker run -d -P --name web --link db:db --wait-for-readiness db training/webapp python app.py

حيث يعتبر is_ready.sh اختبارًا منطقيًا بسيطًا وهو المسؤول عن اتخاذ قرار بشأن وقت اعتبار الحاوية جاهزة.

+1

@ schmunk42 اقتباس لطيف!

+1

+1

+1

+1

+1

+1

+1

+1

+1

في الواقع لقد غيرت رأيي حول هذا ، لذا -1

من المنطقي أن تتحقق الحاوية الخاصة بك من مدى توفر خدمة الطرف الثالث ، ويتم ذلك بسهولة باستخدام نص برمجي صغير للغلاف يستخدم nc على سبيل المثال.

الاعتماد على التأخير مغري ، لكنه حل ضعيف لأن:

  • ستنتظر الحاوية الخاصة بك دائمًا X ثانية قبل أن تصبح جاهزة.
  • قد تظل X ثانية غير كافية في بعض الحالات (على سبيل المثال ، إدخال / إخراج ثقيل أو وحدة المعالجة المركزية على المضيف) ، لذلك لا تزال الحاوية الخاصة بك غير آمنة من الفشل.
  • لا استراتيجية فاشلة.

من الأفضل الاعتماد على كتابة سكربت باش المجمع للأسباب التالية:

  • الحاوية الخاصة بك جاهزة في أقرب وقت ممكن.
  • يمكنك تنفيذ أي استراتيجية فاشلة ، على سبيل المثال ، حاول 10 مرات ثم تفشل ، حاول إلى الأبد ، إلخ. يمكنك حتى تنفيذ التأخير بنفسك عن طريق النوم قبل المحاولة!

من خلال القراءة من خلال هذا الخيط يجب أن أرى أنه لا أحد يذكر الأسرار. أحاول استخدام حاوية بيانات فقط تطلب أسرارًا بمجرد تشغيلها. المشكلة التي أواجهها: إذا استغرقت أسراري وقتًا طويلاً للإرسال / فك التشفير ، فإن الحاوية التابعة الخاصة بي ستفشل لأن البيانات التي تتوقعها غير موجودة. لا يمكنني حقًا استخدام طريقة "ضع كل شيء جيدًا في الحاوية قبل تشغيلها" لأنها أسرار.

أعلم أن هناك بعض الغموض حول حاويات البيانات فقط في الإنشاء بسبب سياق رمز الإرجاع ، ولكن هل هناك طريقة أفضل للقيام بذلك؟

وبالمثل أغير رأيي في هذا ، -1. نهج dnephin صحيح تمامًا. إذا كان _ تطبيقك_ يعتمد على _خدمة_ ، فيجب أن يكون التطبيق نفسه قادرًا على التعامل مع عدم توفر تلك الخدمة بأمان (مثل إعادة إنشاء اتصال). لا ينبغي أن يكون نصًا برمجيًا لغلاف bash أو منطقًا ما في Compose أو Docker ، إنها مسؤولية التطبيق نفسه. أي شيء ليس على مستوى التطبيق سيعمل فقط على التهيئة ؛ إذا تعطلت هذه الخدمة ، فلن يتم تنفيذ برنامج نصي أو شيء ما.

الآن إذا تمكنا من جعل مطوري التطبيقات / المكتبات / إطار العمل يدركون ويدعمون هذه المسؤولية ، فسيكون ذلك رائعًا.

من الصعب التفكير في الأساليب التي قد تتخذها تتضمن تحميل شياطين أخرى غير موصى بها. على سبيل المثال ، حيث لدي تطبيق ريلز يحاول الاتصال بقاعدة بيانات MySQL بينما يقوم تطبيق ريلز آخر حاليًا بترحيل قاعدة البيانات وزرعها عند بدء التشغيل الأولي ، بالنسبة لي لكي أجعل تطبيق ريلز يعرف أنه لا يحاول استخدام قاعدة البيانات ، فأنا إما يجب تعديل مكتبة ActiveRecord (لن يحدث ذلك) أو تشغيل برنامج نصي يستمر في التحقق لمعرفة ما إذا كان قد تم ترحيل قاعدة البيانات وزرعها. ولكن كيف لي أن أعرف على وجه اليقين دون معرفة البيانات التي من المفترض أن تكون هناك و / أو وجود بعض البرامج النصية التي تعمل على النظام الذي يقوم ببذر قاعدة البيانات لإعلام الباقي بالاتصال بها.

ربما أفتقد الحل الواضح ولكن إجابتك "يجب أن يكون المطورون قادرين على التعامل مع هذا في التعليمات البرمجية الخاصة بهم" تتعطل عند استخدام مكتبات الرفوف وعندما لا يكون "من المفترض" أن تقوم بتحميل العناصر الجانبية إلى حاوية.

mattwallington لست متأكدًا حتى من كيفية تقديم
هذا أيضًا محدد بشكل فظيع مما يجعل اختراع Compose أكثر صعوبة. سأقرأ بعض نصائح dnephin أعلاه حول التهيئة / الترحيل / البذر لأن ذلك قد يساعد في حالتك.

أعتقد أنك فاتتك نقطة السطر الأخير ، فالعديد من مكتبات الرفوف لا تعمل _بالتحديد_لأنها لم يتم بناؤها بمرونة. لا يوجد حل سحري يمكنه حل كل هذا يمكن لـ Compose تنفيذه فقط.

فهمت. اقتراحي سابقًا والذي سيعمل مع الكثير من حالات الاستخدام هذه هو أن يكون لديك متغير بيئة مشترك بين الحاويات. يمكن لأحد الجانبين قفل استقصاء المتغير والآخر يمكنه تنفيذ الإجراء ثم تعيين المتغير.

+1 فكرة mattwallington لبيئة مشتركة متغيرة بين الحاويات

شكرا لك. إنه بسيط (على مستوى المنتج. ليس لدي أي فكرة عما قد يتطلبه الأمر من جانب التطوير لأنني لم ألقي نظرة على الكود) ولكنه سيحل الكثير من هذه المشكلات وربما الكثير من المشكلات الأخرى لأنه ليس خاصًا بـ هذه المسألة.

ولكن كيف لي أن أعرف على وجه اليقين دون معرفة البيانات التي من المفترض أن تكون هناك و / أو وجود بعض البرامج النصية التي تعمل على النظام الذي يقوم ببذر قاعدة البيانات لإعلام الباقي بالاتصال بها.

mattwallington : تحقق من رقم الترحيل في جدول المخطط. إذا كان الرقم صحيحًا ، فأنت تعلم أن الترحيل قد تم.

لا ينبغي أن يكون نصًا برمجيًا لغلاف bash أو منطقًا ما في Compose أو Docker ، إنها مسؤولية التطبيق نفسه. أي شيء ليس على مستوى التطبيق سيعمل فقط على التهيئة ؛ إذا تعطلت هذه الخدمة ، فلن يتم تنفيذ برنامج نصي أو شيء ما.

@ agilgur5 : نعم أوافق على أنه سيتم التعامل معه بواسطة التطبيق ، لكن سكربت bash هو حل بسيط للتعامل مع تلك التطبيقات التي لم يتم ترميزها بهذه الطريقة ، على سبيل المثال عن طريق إعادة تشغيل التطبيق عندما لا تكون الخدمة متاحة.

يمكن تقديم الحجج طوال اليوم حول ما يجب أو يمكن فعله على مستوى التطبيق ، ولكن بدلاً من توقع أن يتعامل كل تطبيق في السوق مع هذا الأمر ويصبح رائعًا في التعافي الذاتي (من غير المحتمل) ، فلماذا لا نعارض إضافة بعض الميزات التي يمكن حلها تعمل هذه المشكلة للتطبيقات في عامل الإرساء بغض النظر عن كيفية كتابة تطبيقات الطرف الثالث أو ما يجب عليهم فعله ولكنهم لن يفعلوا ذلك. هذا ما نسيطر عليه. دعونا نحل المشكلة بدلاً من أن نقرر من يجب أن يحلها لأننا لا نملك السيطرة على ذلك.

أتفق معmattwallington. يمكنك طلب هذا الجهد الإضافي للاسترداد الذاتي على مستوى التطبيق من كل مطور واحد لكل صورة حاوية واحدة ، ولكن لا بد أن تكون نسبة كبيرة منهم جاهلة جدًا أو مشغولة جدًا بحيث لا يمكن تنفيذها واختبارها بعناية. ستكون النتيجة النهائية أن بعض الحاويات تعرف كيفية التعافي الذاتي بينما لا يعرف الكثير منها. وكمستخدم ، ستكون بدون أي أدوات لإدارة تلك التي لا تفعل ذلك.

فكرة خطرت لي للتو: بدلاً من حل المشكلة عن طريق تأخير بدء تشغيل الحاوية ، يمكن أن يحاول Compose استعادة الحاوية الفاشلة.

شيء مثل recover: auto سيعيد تشغيل الحاوية الفاشلة 5 مرات في 2 و 4 و 8 و 16 و 32 ثانية ثم يستسلم تمامًا.

هل هناك من _فكر_ في فكرة حاوية تبعية الحاوية؟

فمثلا:

"" #! yml
ديسيبل:
الصورة: mysql

أنتظر لأجل:
الروابط:
- ديسيبل
أحجام:
- /var/lib/docker.sock :/docker.sock
- $ {PWD} /docker-compose.yml:/docker-compose.yml
الأمر: docker-compose up -d app

تطبيق:
الصورة: myuser / myapp
الروابط:
- ديسيبل
""

الفكرة الأساسية هنا هي أنك _ تحل_ مشكلة الحاويات التي لا تحتوي على آليات الاسترداد الذاتي من خلال إنشاء خدمة مخصصة قابلة لإعادة الاستخدام يمكن نشرها على Docker Hub بحيث يمكن للجميع إدخالها في تكوينها.

سأكون على استعداد حتى لوضع نموذج أولي لمثل هذه الخدمة / الحاوية / الصورة والسماح للآخرين بالتبديل مع هذا لمعرفة كيف سيكون سعرها ...

prologic مشكلة التبعية هي ، كيف تتأكد من أن الخدمة التي تريد التحدث إليها

قد تستجيب حاوية db لـ ping ولكنها تقوم ببعض التنظيف / التهيئة المسبق لقاعدة البيانات قبل أن تكون متاحة بالفعل لأوامر mysql / psql .

هل يمكن تحديد هذا الاختبار بطريقة قابلة للتكوين و / أو تقديمه في برنامج نصي إلى خدمة من النوع waitfor قابلة لإعادة الاستخدام؟

IMHO ، هذه مشكلة شائعة جدًا ولكل شخص متطلباته الخاصة. كما تم التعليق عليه من قبل في هذه المسألة ، أعتقد أن عامل الرصيف يمكنه (ويجب عليه) توفير طريقة للحاوية لتحديد أمر بسيط للتحقق من جاهزيتها. من الواضح أننا كمطورين يجب أن نوضح بالتحديد كيفية التحقق من جاهزية كل حاوية.

بعض العلامات الاختيارية لتشغيل Docker للإشارة إلى أمر فحص داخلي سيكون رائعًا لربطه لاحقًا من حاوية أخرى باستخدام علامة خاصة للارتباط.

شيء مثل:

$ sudo docker run -d --name db training/postgres --readiness-check /bin/sh -c "is_ready.sh"
$ sudo docker run -d -P --name web --link db:db --wait-for-readiness db training/webapp python 

Where is_ready.sh هو اختبار منطقي بسيط يكون مسؤولاً عن قرار متى تعتبر الحاوية جاهزة.

يمكن أن يكون أيضًا أمرًا للحاوية للتحقق يدويًا من جاهزيتها.

Where is_ready.sh هو اختبار منطقي بسيط يكون مسؤولاً عن قرار متى تعتبر الحاوية جاهزة.

مما يعني أنه يجب على كل مطور إعداد صوره / حاوياته لتشمل _شيء _ يمكن استخدامه للتحقق مما إذا كانت الحاوية جاهزة.

وهو ما يعيدنا إلى المربع 1. المطورون هم المسؤولون عن جعل حاوياتهم مرنة في مواجهة انقطاع الخدمة / وقت بدء التشغيل ، لأنهم هم الوحيدون الذين يمكنهم معرفة "ماذا" يعني ذلك بالنسبة لوضعهم؟

أو أتغاضى عن شيء ما هنا؟

أنا موافق. تقع المسؤولية على عاتق المطور / الحاوية / الخدمة

يوم الخميس ، 30 يوليو 2015 ، Sebastiaan van Stijn [email protected]
كتب:

Where is_ready.sh هو اختبار منطقي بسيط مسؤول عن
قرار عندما تعتبر الحاوية جاهزة.

مما يعني أنه يجب على كل مطور تجهيز صوره / حاوياته لـ
تشمل _something_ التي يمكن استخدامها للتحقق مما إذا كانت الحاوية
جاهز.

وهو ما يعيدنا إلى المربع 1. المطورين هم المسؤولون عن
مما يجعل حاوياتهم مقاومة لانقطاع الخدمة / وقت بدء التشغيل ، لأن
هم الوحيدون القادرون على معرفة "ماذا" يعني ذلك بالنسبة لوضعهم؟

أو أتغاضى عن شيء ما هنا؟

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/docker/compose/issues/374#issuecomment -126278215.

جيمس ميلز / برولوجيك

البريد الإلكتروني: [email protected]
W: prologic.shortcircuit.net.au

نعم طبعا. بالنسبة لي ، الشخص الوحيد الذي يعرف حقًا متى تكون الحاوية جاهزة هي الحاوية الخاصة. لا يستطيع Docker معرفة أي شيء عن محتوى الحاوية. إنه صندوق أسود. الشيء الوحيد الذي يمكن أن تفعله هو أن تطلب من الحاوية (مع تحديد إجراء مخصص عندما تريد التشغيل ، كما اقترحت ، أو أي طريقة شائعة أخرى لاختبارها). ومن الواضح أن المطور هو الوحيد الذي يعرف ما يحتاجه ومحتوى الصندوق الأسود.

نعم هذا صحيح!

في يوم الخميس ، 30 يوليو 2015 ، كتب adrianhurt [email protected] :

نعم طبعا. بالنسبة لي ، الشخص الوحيد الذي يعرف حقًا متى تكون الحاوية
جاهز هو الحاوية الخاصة. لا يستطيع Docker معرفة أي شيء عن محتوى
حاوية. إنه صندوق أسود. الشيء الوحيد الذي يمكنها فعله هو أن تطلب من
حاوية (مع إجراء مخصص محدد عندما تريد التشغيل ، مثل I
المقترحة ، أو أي طريقة شائعة أخرى لاختبارها). ومن الواضح أن المطور
هو الوحيد الذي يعرف ما يحتاجه ومحتوى ذلك الصندوق الأسود.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub
https://github.com/docker/compose/issues/374#issuecomment -126285056.

جيمس ميلز / برولوجيك

البريد الإلكتروني: [email protected]
W: prologic.shortcircuit.net.au

حسنًا - من أجل جميع البرامج قيد التطوير أو القديمة التي لا يمكنها التعامل مع فشل الشبكة ، لنفترض أننا نريد حل هذه المشكلة بعد كل شيء. أنا لا أقول إننا نفعل ذلك ، أنا فقط أريد أن أشعر بالنحو ، والدلالات والتعقيد.

يبدو أن الحد الأدنى من مجموعة المتطلبات هو:

  • أريد من Compose الانتظار لبدء خدمة حتى تصبح خدمة أخرى "جاهزة".
  • أريد تعريف "جاهز" على أنه "يقبل اتصالات TCP على المنفذ X" ، أو أي شيء آخر.

لنفترض أيضًا أن الفحوصات الصحية لن تجعله في Docker لفترة من الوقت.

أتساءل عما إذا كان من الممكن حلها في الحالة العامة من خلال إتاحة إمكانية انتظار خروج حاويات خدمة أخرى. يمكنك بعد ذلك كتابة فحصك الصحي باعتباره مجرد خدمة أخرى.

web:
  image: mywebapp
  links: ["db"]
  wait_for: ["db_wait"]

db_wait:
  image: netcat
  links: ["db"]
  command: sh -c "while ! nc -w 1 -z db 5432; do sleep 1; done"

db:
  image: postgres

إذا كنت تريد نوعًا من الفحص الصحي المخصص ، فحدده في خدمة "الانتظار". هنا ، سيتم الخروج من db_wait بمجرد وجود mytable في قاعدة البيانات mydb :

db_wait:
  image: postgres
  links: ["db"]
  command: sh -c "while ! psql --host db --dbname mydb -c "\d mytable"; do sleep 1; done"

إذا كان لديك برنامج نصي لإعداد db ليتم تشغيله أولاً ، فيمكنك جعل هذا الشيء الذي تنتظره:

web:
  image: mywebapp
  links: ["db"]
  wait_for: ["prepare_db"]

prepare_db:
  image: prepare_db
  links: ["db"]
  command: ./prepare.sh

db:
  image: postgres

قد تكون الحالة الأولى (انتظر حتى تقبل الحاوية اتصالات TCP) شائعة بما يكفي لتكون جديرة بالدعم خارج الصندوق.

web:
  image: mywebapp
  links: ["db"]
  wait_for_tcp: ["db:5432"]

db:
  image: postgres

هناك تأثير خفي في كل هذا: docker-compose up -d يجب أن يتم حظره أثناء تشغيل الفحص الصحي الوسيط أو خدمة التحضير ، حتى يتمكن من بدء خدمة (خدمات) المستهلك بمجرد الانتهاء.

نعم. ومع ذلك ، في رأيي ، يجب أن يوفر عامل الإرساء طريقة لتحديد متى تكون الحاوية جاهزة ، ومن ثم يمكن للكتابة إدارتها. يمكننا بعد ذلك طرح مشكلة جديدة مباشرة في عامل الإرساء. بالنسبة لي ، يمكن أن يكون شيئًا مثل:

web:
  image: mywebapp
  links: ["db"]
  wait_for: ["db"]

db:
  image: postgres
  ready_when: sh -c "while ! psql --host db --dbname mydb -c "\d mytable"; do sleep 1; done"

بعد ذلك ، ليست هناك حاجة لإنشاء خدمات جديدة كحل بديل

متفق عليه. امنح المرونة للمطور. قد لا يكون إيقاف الحاوية مؤقتًا هو ما يحتاج المطور أن يفعله أثناء انتظاره. ربما هناك بعض البادئات الخاصة بها التي يجب أن تحدث ولكن بعد ذلك انتظر حتى يصبح db جاهزًا للاتصالات. لذلك إذا كان متغير بيئة مشتركًا بسيطًا ، فإنه يمكّن المطور من استخدامه كما يحتاجون.

كيف يمكن تحديث متغير البيئة المشتركة؟ على حد علمي ، لا يمكنك إجراء تغييرات على مجموعة متغيرات البيئة العملية بمجرد أن تبدأ.

يمكنك تغييرها في جلسة bash على سبيل المثال ، لكن لن يتم نشرها في جميع الطبقات الأخرى.

للقيام بذلك ، يجب الالتزام بالتغيير وإعادة تشغيل الحاوية. هذا عديم الفائدة في هذا السيناريو.

ما هو أكثر من ذلك ، حتى إذا كان المتغير يمكن أن يتغير ، فإن العملية في الحاوية ستحتاج إلى معرفتها لاستقصائها ، مما يجعل هذا غير حل للبرنامج القديم الذي تستخدمه هذه الميزة ظاهريًا.

نظرًا لأننا نتحدث فقط عن حل هذه المشكلة للحاويات القديمة في بيئات التطوير ، أعتقد أنه يمكن حلها كأداة تقع فوق إنشاء docker-compose ps -s (قائمة الخدمات بترتيب التبعية ، # 1077).

باستخدام هذين الأمرين ، يمكن كتابة أداة تقوم بشيء مثل هذا:

  1. قم بتشغيل docker-compose ps -s للحصول على قائمة بأسماء الخدمات بترتيب التبعية
  2. قم بتشغيل docker-compose up -d --no-recreate <first service from the list>
  3. قم بتشغيل الأمر "healthcheck" لتلك الخدمة حتى تصبح سليمة أو تنتهي المهلة. قد يكون هذا طلب HTTP ، أو مكالمة docker exec
  4. كرر 2 و 3 لكل خدمة في القائمة
  5. قم بتشغيل docker-compose logs (أو لا تفعل ذلك إذا تم تمرير -d )

بهذه الطريقة ، يمكن أن يكون التكوين "healthcheck" و "انتظار" خارجيًا للإنشاء ، لكنني لا أعتقد أن المطور مطالب بتوفير أي شيء فوق ما هو مطلوب إذا تم تنفيذه كجزء من الإنشاء نفسه.

أي سبب لن يعمل هذا؟

أنا سعيد لأننا حددنا المجال للحاويات القديمة ، وهذا أكثر منطقية: +1:

dnephin أعتقد أن هذا رائعًا من المنظور الفوري أنه مرن وأن Compose لا يحتاج إلى بعض الدعم المدمج للحاويات القديمة ، لكني أرى مشكلة فورية مشابهة لما وصفه mattwallington ، ماذا لو كانت الحاويات الأخرى تستطيع قم بتشغيل بعض الأشياء (مثل init) قبل الاتصال بهذه الخدمة؟ الحظر على هذه الحاوية _works_ ، ولكنه ليس مثاليًا (وهذا ما قيل ، لست متأكدًا مما إذا كان هناك حل مثالي لحاوية قديمة). هذا من شأنه أن يحل مشكلتي على الأقل ، الآن يجب أن أجد تلك التذكرة!

+1

لتتمكن من تحديد التبعيات في ملفات تكوين عامل الإرساء ...

... عدم استخدام الروابط (لأنها غير متوافقة مع net = host). كنت أعتقد أن هذه هي الوظيفة أو على الأقل مصدر قلق أداة إدارة الحاويات المتعددة لمعرفة الترتيب الذي يجب أن تبدأ فيه الأشياء ، تمامًا مثل الدمية التي لديها شجرة تبعية خاصة بها ، ولكن في بعض الأحيان يعرف المستخدم بشكل أفضل ويمكنه تجاوز. عند قراءة كل ما سبق ، يبدو لي أن الصعوبة الوحيدة هي تحديد متى تكون الحاوية "أعلى" بحيث يمكن بدء الحاوية التالية في سلسلة التبعية. قد تكون هذه بالضبط نفس آلية آلية الارتباط (في الوقت الحالي) - أي شيء أفضل من لا شيء. في وقت لاحق ، يمكن تحديد توضيح "تنفيذ التبعية" بواسطة ملف إنشاء عامل الإرساء ، على سبيل المثال - هذه التبعية من المهم أن الحاوية تعمل

depends_on:
  container: foo
  requires: running

أو هذه التبعية ، من المهم أن تستمع منافذ TCP الحاويات.

depends_on:
  container: foo
  requires: listening

إن القول بأنها وظيفة أداة خارجية أو نصوص برمجية فوق عامل الإرساء هو بمثابة قول إن عامل البناء ليس لديه أي اهتمام أو مسؤولية حقيقية عن تنسيق تشغيل حاويتين أو أكثر على نفس الجهاز. إذن ما هو الغرض منه؟

كنت أعتقد أن هذه هي الوظيفة أو على الأقل مصدر قلق أداة إدارة الحاويات المتعددة لمعرفة الترتيب الذي يجب أن تبدأ فيه الأشياء

لا ليس بالضرورة. للأسباب الموضحة عدة مرات بالفعل في هذا الموضوع ، أعتقد أنه لا يوجد سوى عذرين لتسليم هذه الوظيفة إلى أداة إدارة الحاويات:

  1. أنت تقوم بتشغيل صور حاوية جاهزة غير قابلة للتكيف مع عدم توفر خدمات المنبع التي تعتمد عليها ، ولأسباب فنية أو تجارية لا يمكنك تغييرها أو تمديدها.
  2. أنت تقوم بتشغيل برنامج في بيئة تطوير بحتة ، وليس في بيئة إنتاجية ، ولديك أشياء أفضل لتمضية الوقت فيها بدلاً من تطبيق المرونة.

ومع ذلك ، إذا كنت تتحكم في برنامجك وتخطط لنشره في الإنتاج ، فلا يمكنك الاعتماد على أداة خارجية تبدأ الأشياء بالترتيب الصحيح فقط ، حتى لو كنت قد حددت شروط الاستعداد الخاصة بك بعناية. إنه ليس حلًا للمشكلة الأساسية ، وسوف يسقط نظامك في اللحظة التي يحدث فيها عطل في الشبكة. في أحسن الأحوال ، سيتعين عليك إعادة تشغيل جميع حاويات الواجهة الأمامية للويب تلقائيًا في كل مرة يحدث فيها ذلك ، ولا يمكنني أن أرى أن ذلك يمثل قدرًا مقبولًا من وقت التوقف عن العمل لأي شخص.

أتفق معك على أن البرامج المكتوبة جيدًا ستتعامل مع انقطاع الشبكة. أعتقد أننا نتفق على أنه ليست كل البرامج مكتوبة جيدًا ، ولا يفكر المطورون دائمًا في جميع حالات الاستخدام الممكنة.

ربما أرغب في تشغيل حاوية عملاء تشغل JVM ، وأداة مراقبة أخرى لإرفاقها ، سواء في مساحة اسم PID للمضيف بحيث يمكن للمرء مراقبة الآخر وأنا مدعوم ومرخص فقط لتشغيل مثل هذه الأداة مع صورة البائعين المصرح لهم . إذا كانت أداة المراقبة تراقب JVMs الموجودة ، فمن المهم ترتيب بدء التشغيل (من الواضح). من المحتمل أن يكون هناك المئات من حالات الاستخدام التي يكون فيها الأمر مهمًا ، وبعضها يتضمن شبكات (تم ذكر كل من mysql و elasticsearch ومجموعات اكتشاف الخدمة) ، ولكن بعضها يتضمن أشياء أخرى يمكن مشاركتها باستخدام مساحات الأسماء المختلفة بشكل فعال.

لذلك أنا أتفق بالتأكيد مع حالة الاستخدام (1) ، في ذلك في بعض الظروف لا يمكنك تغيير الحاوية

ولكن أيضًا بمجرد أن تهتم الأداة بأي شيء متعدد ، فإنها تعارض الطلب على الفور. إذا كان الطلب مهمًا وكانت الطريقة الوحيدة لضمان الأمر هي كتابة نص برمجي حول عامل الإرساء لإنشاء شيء ما أولاً ، ثم إنشاء شيء آخر ، فقد لا يكون عامل الإرساء موجودًا في السلسلة ، بخلاف الحقيقة JSON / YAML أجمل من cmdline args.

IMHO في نهاية المطاف الأداة إما مفيدة أو لا لمجموعة من حالات الاستخدام. من الواضح أن Docker-Compose مفيد لبدء التشغيل غير المنظم لحاويات متعددة على نفس المضيف. إذا كان هناك عدد كافٍ من الأشخاص وحالات استخدام كافية تتعلق بالطلب ولم تعالجهم الأداة ، فسيقوم الأشخاص بالذهاب إلى مكان آخر بحثًا عن حالات الاستخدام هذه ، وهو أمر مخز.

على أي حال أرى أنني أعيد صياغة الحجج القديمة ، لذا سأخرج من هذا الموضوع الآن ..

هذه هي الحجة نفسها التي تم ذكرها عبر آلاف الخيوط حول العديد من موضوعات التطوير المختلفة "إذا تمت كتابة جميع التعليمات البرمجية بشكل صحيح من قبل الجميع ، فلن تكون هناك حاجة إلى مثل هذه ، لذلك دعونا لا نفعل ذلك". وهذا يعادل القول: إذا توقف جميع الناس في العالم عن حرق الوقود الأحفوري أو استخدام الكهرباء ، فيمكننا حل المشاكل التي نتسبب فيها لكوكبنا. انت على حق. إذا فعلت جميع التطبيقات ما ينبغي لها ، فلن نتحدث هنا عن هذا الأمر. لكننا نعيش على الأرض. مكان به عيوب هائلة مع نوع من الكائنات التي تميل إلى تعلم الأشياء بالطريقة الصعبة. نفس الأشخاص الذين يطلقون الشركات على أرض الواقع فقط لأنهم يبنون "الحد الأدنى من المنتجات القابلة للتطبيق" من أجل الصلاة من أجل الوصول إلى الجولة التالية من التمويل أو العميل التالي الذي قد يسمح لهم يومًا ما ببناء الإصدار الذي يرغبون فيه .

العالم ليس مثاليًا ولن يكون أبدًا ، ولذا يمكننا فقط أن نفعل ما لدينا في سيطرتنا. وفي هذه الحالة ، الشيء الوحيد الذي أملكه هو محاولة إقناعكم جميعًا (ويعرف أيضًا باسم الأشخاص الذين يطورون الأداة التي أحبها تمامًا وسأستخدمها بجنون إذا كان لديها هذه الميزة الوحيدة فقط) لبنائها في طريقة يمكنها من خلالها التعامل مع البرامج الموجودة في العالم الذي نعيش فيه. وليس البرنامج الذي كنا نتمنى أن نعيش فيه.

في 31 تموز (يوليو) 2015 ، الساعة 3:42 صباحًا ، كتب Aanand Prasad [email protected] :

كنت أعتقد أن هذه هي الوظيفة أو على الأقل مصدر قلق أداة إدارة الحاويات المتعددة لمعرفة الترتيب الذي يجب أن تبدأ فيه الأشياء

لا ليس بالضرورة. للأسباب الموضحة عدة مرات بالفعل في هذا الموضوع ، أعتقد أنه لا يوجد سوى عذرين لتسليم هذه الوظيفة إلى أداة إدارة الحاويات:

أنت تقوم بتشغيل صور حاوية جاهزة غير قابلة للتكيف مع عدم توفر خدمات المنبع التي تعتمد عليها ، ولأسباب فنية أو تجارية لا يمكنك تغييرها أو تمديدها.

أنت تقوم بتشغيل برنامج في بيئة تطوير بحتة ، وليس في بيئة إنتاجية ، ولديك أشياء أفضل لتمضية الوقت فيها بدلاً من تطبيق المرونة.

ومع ذلك ، إذا كنت تتحكم في برنامجك وتخطط لنشره في الإنتاج ، فلا يمكنك الاعتماد على أداة خارجية تبدأ الأشياء بالترتيب الصحيح فقط ، حتى لو كنت قد حددت شروط الاستعداد الخاصة بك بعناية. إنه ليس حلًا للمشكلة الأساسية ، وسوف يسقط نظامك في اللحظة التي يحدث فيها عطل في الشبكة. في أحسن الأحوال ، سيتعين عليك إعادة تشغيل جميع حاويات الواجهة الأمامية للويب تلقائيًا في كل مرة يحدث فيها ذلك ، ولا يمكنني أن أرى أن ذلك يمثل قدرًا مقبولًا من وقت التوقف عن العمل لأي شخص.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub.

+1aanand. هذا ليس شيئًا ستتمكن من تقييده في النطاق. الميزة ، إذا تم تنفيذها ، يجب أن تكون شيئًا يمكن للناس الاعتماد عليه. لقد قاموا بترميز بنية تحتية "متينة" لفترة طويلة ويستغرق الأمر وقتًا طويلاً لتحويل الجماهير. سيستخدمون هذا لفترة طويلة قادمة.

أود أن أكرر أننا لم نستبعد تنفيذ شيء ما للتخفيف من مشكلة تبعيات توقيت بدء التشغيل بين الحاويات - لقد قمت برسم حل واحد ممكن بالأمس فقط ، في هذا الموضوع بالذات .

لكني أريد أن نكون على نفس الصفحة فيما يتعلق بمن هذه الميزة ، وما هي المشاكل التي ستحلها ، وما هي المشاكل التي لن تحلها ، وإلى أي درجة يمكن الاعتماد عليها. هذا ما أحاول الشعور به.

علاوة على ذلك ، نظرًا للتعريفات المتعددة للجاهزية الموجودة ("الحاوية بدأت" مقابل "الحاوية تقبل اتصالات TCP" مقابل "ممرات فحص الصحة المخصصة") ، والتعقيد المختلف في تنفيذ كل منها ، أريد الحصول على مقارنة فكرة عن عدد الأشخاص الذين سيستفيدون من الدعم الفوري لكل واحد.

من الأساليب الشائعة لمزامنة الخدمات شيء مثل "سجل الخدمة" باستخدام etcd أو ما شابه. ماذا عن خدمة الانتظار:

web:
  image: mywebapp
  links: ["db"]
  wait_for_service:
    type: etcd (or consul, or zk)    -- or use swarm type notation
    addr: http://my.etcd.com/
    path: postgres.service

db:
  image: postgres

لا يعرف Compose ما إذا كانت الخدمة جاهزة حقًا ولكن يمكنه البحث عن البيانات الموجودة في السجل وبدء الحاوية التابعة بناءً على ذلك. تقع على عاتق الخدمات (مثل postgres) مسؤولية نشر توفرها في السجل ، لذا بالنسبة للتطبيقات القديمة ، فإن نوعًا من نصوص التغليف سيفعل ذلك: بدء تشغيل التطبيق ، ومشاهدة المنفذ ليتم تشغيله ، ثم النشر في التسجيل.

مرحباaanand.

كنت أناقش هذا اليوم مع bfirsh على

على وجه التحديد ، عند إنشاء نظام موزع من العديد من المكونات الصغيرة التي تم إرساءها ، وجدت أن هناك حاجة لإجراء اختبارات تكامل والتي تضم جميع تطبيقات الواجهة الرئيسية وتبعياتها ، ثم أجريت اختبارات مختلفة ضدها قبل أن تمزقها مرة أخرى.

يؤدي هذا إلى مشكلات مثل أخذ Riak بعض الوقت للبدء مقارنة بأي شيء آخر يستخدمه.

لن أعارض بشكل خاص قولكم جميعًا "تبدأ الحاويات بلا تزامن ، وتتعامل معها" ، ولكن التصميم حول كل خدمة يعرض فحصًا صحيًا ثابتًا سيحتوي على الأقل على "التعامل معها" لتنفيذ واحد لكل خدمة بدلاً من وجود رمز للتعامل مع إعادة محاولة الاتصالات في كل تطبيق يعتمد على الخدمة.

الخدمات التي تحدد الفحص الصحي الخاص بهم مفيدة أيضًا لأغراض المراقبة.

elliotcm متفق عليه على النقطتين.

للاختبار على CI الخاص بنا ، قمنا ببناء أداة مساعدة صغيرة يمكن استخدامها في حاوية Docker لانتظار الخدمات المرتبطة لتكون جاهزة. يقوم تلقائيًا بالعثور على جميع خدمات TCP المرتبطة من متغيرات البيئة الخاصة بهم ويحاول بشكل متكرر ومتزامن إنشاء اتصالات TCP حتى تنجح أو تنتهي مهلتها.

كتبنا أيضًا منشور مدونة يصف سبب بنائه وكيف نستخدمه .

meeee التي تبدو جميلة ومفيدة حقًا! هل يمكنك أن تبين لنا أمثلة على كيفية تطورها ؛ على وجه الخصوص في الاستخدام مع عامل ميناء يؤلف؟

كانت لدي حالة أكثر تعقيدًا اليوم ، حيث كنت أبدأ حاوية mysql لأول مرة. تقوم الحاوية بتمهيد نفسها عند التشغيل لأول مرة ، وإعادة تشغيل البرنامج الخفي لقاعدة البيانات عند تهيئتها. تسبب هذا في تشغيل عمليات التحقق من توفر المنفذ قبل الأوان ، وبدأت الحاويات التابعة ولكنها فشلت في الاتصال. كان هذا في بيئة CI ، حيث نريد إعداد الأشياء بالكامل من البداية.

أنا حريص جدًا على التأليف لدعم نوع من سلوك الانتظار / التحقق ، ولكن هناك بعض الحالات المخادعة المخادعة. أنا سعيد للمشاركة في المناقشات.

prologic كل ما عليك فعله هو تشغيل الأمر waitforservices في حاوية Docker اعتمادًا على الخدمات / الحاويات الأخرى قبل تشغيل التطبيق أو الاختبارات. يعثر على جميع الخدمات المرتبطة ويعمل حتى يتمكن من الاتصال بها أو يمر وقت معين (60 ثانية افتراضيًا). ما عليك سوى تشغيل كل التعليمات البرمجية التي تعتمد على الخدمات الأخرى بعد إنهاء الثنائي (قد ترغب في التحقق من حالة الخروج رغم ذلك).

pugnascotia يمكن لخادم قاعدة البيانات الخاص بك الاستماع إلى المضيف بدء التشغيل - سيتعين عليك كشف نوع من المؤشرات ما إذا كانت الحاوية جاهزة على أي حال. نحن لا نستخدم MySQL ، لكن خدمة waitforservices تعمل بشكل مثالي مع صورة postgres الرسمية .

aanand Postgres هو مثال ممتاز للاختيار في الواقع ، لأن انتظار فتح منفذ TCP _ ليس كافيًا - إذا قمت بذلك في هذا النوع من سيناريو (عامل الإرساء) ، فستتعرض أحيانًا لخطأ مثل FATAL: the database system is starting up. إذا كانت الحاوية الأخرى الخاصة بك تتصل بسرعة كبيرة بعد فتح اتصال TCP. لذلك يبدو أن psql ضروريًا إذا كنت تريد التأكد من أن postgres جاهز - أستخدم select version() ولكن ربما يوجد بديل أخف.

هناك مكون إضافي خاص بـ

باستخدام هذا كحل بديل (لست متأكدًا من أنه مضاد للرصاص):

db:
  image: postgres:9.3
  ports:
    - "5432:5432"
createdbs:
  image: postgres:9.3
  links:
    - db
  command: >
    /bin/bash -c "
      while ! psql --host=db --username=postgres; do sleep 1; done;
      psql --host=db --username=postgres -c 'CREATE DATABASE \"somedatabase\";';
    "

لقد كنت أستخدم أساليب مماثلة لـolalonde. عند استخدام علامات الاقتباس الفردية للأمر الذي تم تنفيذه بعد /bin/bash -c ، فأنا أيضًا قادر على استخدام متغيرات البيئة التي يتم إعادة استخدامها من الروابط عند التطبيقات الأخرى حتى أتمكن من استخدام أسماء المستخدمين وكلمات المرور دون الحاجة إلى الاحتفاظ بها في قسمين أماكن. يعمل هذا بشكل جيد في المواقف التي لدي فيها خدمة ، مثل واجهة برمجة التطبيقات (API) ، والتي تحتاج إلى قاعدة بيانات ليتم تشغيلها ، وتمهيد البيانات المناسبة عن طريق تشغيل فحص الاستعلام لمعرفة ما إذا كان يوجد جدول أو سجل معين. هذا يعني أيضًا أنني بحاجة إلى تثبيت نوع من العميل في الحاوية للاستعلام عن قاعدة البيانات بشكل صحيح ولكنها تعمل.

+1 أنا مهتم حقًا بهذه الوظيفة

+1 على التبعيات. أوافق على أن البنية الأساسية يجب أن تكون قوية بما يكفي لدعم أي طلب بدء. ولكن ، في كثير من الأحيان ، يكون القيام بذلك غير عملي.

يبدو أن دفع هذه الميزة إلى الوراء ينبع من محاولة الآخرين إملاء العمارة من بعيد ؛ حيث لا يحق لهم فعل ذلك. تسمح هذه الميزة بالعمل حول معيد البناء الذي يستغرق وقتًا طويلاً ؛ مع القليل من القيمة على المدى الطويل. (إعادة بناء ديون من أجل إعادة بناء ديون).

نعم ، قلت "حل بديل" ؛ وأشعر بالقذارة. لكن التأليف بالنسبة لي يتعلق حقًا بتمكين الآخرين من أن يكونوا منتجين. هذا التكوين البسيط يتيح ذلك.

إذا كانت هذه الميزة موجودة في الأداة ، فيمكنني حل مشكلتي في غضون دقيقة والانتقال إلى إضافة قيمة حقيقية. بدلاً من ذلك ، أقوم بضرب رأسي بالحائط في محاولة للتغلب على مشكلات بدء التشغيل مع التبعيات الخارجية.

beardface، والجميع: ميزة ما، على وجه التحديد، فإن تمكنك من المضي قدما في تطوير التطبيق الخاص بك؟

  1. القدرة على تحديد تلك الخدمة يجب أن تنتظر A للبدء حتى تبدأ الخدمة B؟ (والتي ، ضع في اعتبارك ، ما زالت لن تحل حالة السباق عند بدء تشغيل الحاوية ولكن غير جاهز لقبول الاتصالات)
  2. القدرة على تحديد أن الخدمة "أ" يجب أن تنتظر حتى تبدأ الخدمة "ب" بقبول الاتصالات؟ (التي ، ضع في اعتبارك ، لا تزال لن تحل حالة السباق عند استماع الحاوية ولكن لم تنته من التهيئة - على سبيل المثال ، حاوية postgres تنشئ قاعدة بيانات عند بدء التشغيل ، لاستخدام مثال rarkins )
  3. القدرة على تحديد فحص صحي للخدمة B ، وتحديد تلك الخدمة يجب أن تنتظر A للبدء حتى يمر الفحص الصحي للخدمة B؟

aanand رقم 3 هو تصويتي. إنه يمنح المطور المرونة لاختيار منطق الفحص الصحي بدلاً من الاعتماد مرة أخرى على الخدمة ليقرر متى يحين الوقت. بالنسبة لحالة الاستخدام المحددة هذه ، يكون المزيد من حرية المطور أفضل. من المستحيل توقع جميع أنواع التطبيقات التي سيتم تثبيتها في الحاويات.

+3

سيكون من الجيد تضمين بعض الفحوصات الصحية الأساسية. شيء مثل _http 200 ok على المنفذ 80_ شائع جدًا لدرجة أنه قد يستحق الجهد المبذول.

سيكون من الجيد أن يكون لديك "بطاريات مضمنة" رقم 3 (لذا أجرؤ على قول كل ما سبق؟)

أي إمكانية مدمجة لـ "الحاوية قيد التشغيل" و "الملف موجود" و "المنفذ مفتوح" نوع الانتظار ثم طريقة للسماح للأشخاص بتحديد عمليات التحقق الخاصة بهم "طبقة التطبيق".

3 يحصل على تصويتي

3 هي أكثر عمومية 2 هي أكثر عمومية 1. الجميع سيفضل 3 ، لكن 2 أو 1 ستكون جيدة بما يكفي للبعض.

التصويت لـ 3

من الواضح أن الخيار الثالث. هناك الكثير من الحالات فقط في هذه المناقشة. لذا فإن الخيارين الأول والثاني سيكونان رائعين وسيكون الكثير من الناس سعداء ، لكن القضية ستبقى مفتوحة.

التصويت لـ 3

التصويت لـ 3

التصويت لـ 3. مهتم باختبار الإصدار التجريبي أيضًا.

التصويت لـ 3.

التصويت لـ 3. مهتم باختبار الإصدار التجريبي أيضًا.

التصويت لـ 3

3

شكرا لكم جميعا. يمكنك التوقف عن التصويت الآن - أعتقد أن الرسالة واضحة.

سأكون مهتمًا بالتعليقات على التصميم الذي اقترحته في https://github.com/docker/compose/issues/374#issuecomment -126312313 - أي مقترحات تصميم بديلة ، إلى جانب المناقشات حول نقاط القوة / الضعف فيها.

قد تكون طريقة الراحة wait_for_tcp مفيدة ، لكن ليس من الواضح بالنسبة لي كيف أن وجود حاوية منفصلة لإجراء الفحص الصحي أسهل من القيام بذلك في نفس الحاوية كما هو موضح بواسطة olalonde و mbentley أعلاه .

ماذا عن فعل شيء مثل ما يفعله alexec في Docker-maven-plugin؟ لقد صمم بشكل صريح تكوينه ليكون مشابهًا لـ docker-compse / fig وحتى الآن ، كان يعمل بشكل رائع لمشاريعي.

healthChecks:
  pings:
     # check this URL for 200 OK
     - https://localhost:8446/info
     # check another URL with non-default time out, with a pattern, and non checking SSL certificates
     - url: https://localhost:8446/info
       timeout: 60000
       pattern: pattern that must be in the body of the return value
       sslVerify: false
  logPatterns:
     - pattern that must be in log file
     - pattern: another pattern with non-default timeout
       timeout: 30000

المصدر: https://github.com/alexec/docker-maven-plugin/blob/master/USAGE.md

التحقق من أن اتصال TCP غير كافٍ لمعرفة أن قاعدة البيانات قد بدأت. أعتقد أنه من الأفضل أن يكون لديك بعض الأوامر وهو التحقق من صحة قاعدة البيانات.

ceagan من هذا

healthChecks:
  custom:
    # retry this command until it returns success exit code
    - cmd: psql --host=localhost --username=postgres
      sleep: 1s

أعتقد أيضًا أن checks سيكون أفضل من healthChecks لأنه لا داعي لتذكر اصطلاح الحالة. قد يكون مفيدًا أيضًا أن يكون لديك wait (عدد الثواني التي يجب الانتظار قبل البدء في إجراء الفحوصات الصحية) ، attempts (كم مرة يجب فحص الصحة قبل الاستسلام) ، retire (كم ثانية يجب الانتظار قبل الاستسلام تمامًا) المعلمات.

هذا يسير في اتجاه كيف حلها إطار الماراثون. التبعيات الأساسية بالإضافة إلى الفحوصات الصحية . نظرًا لأنه شائع جدًا لبدء تشغيل حاويات docker ، فمن المفيد التحقق من خياراته (المهلات ، والفاصل الزمني ، ورموز الاستجابة وما إلى ذلك) لاعتمادها في الإنشاء.

نفس الشيء هنا ، الخيار 3.

+1

+1

+1

سألتزم بنص انتظار مخصص ، ومع ذلك ، سيكون رائعًا جدًا.

+1

+1

الخيارات 3 - التحقق من الصحة يبدو جيدًا.

+1

+1

+1

+3.
لإضافة بعض الأفكار الأخرى إلى المناقشة ، فإن الخيارات المقترحة aanand تقول حقًا: حالة الحاويات هي مسؤولية عامل الميناء ، وليس تكوين عامل الميناء. يمكن لـ Docker-compose تنفيذ جميع حالات الاستخدام هذه بطريقة نظيفة وأنيقة ، إذا قدم عامل الإرساء معلومات الحالة. لكن عامل الميناء لا يفعل ذلك. يبدو أنه يلتزم برؤية الحاويات الفورية عديمة الحالة ، والتي يتم إطلاقها بسرعة كبيرة بحيث لا تكون هذه الأنواع من مشكلات المزامنة مهمة.
في حالتي ، أتابع فكرة أن أكون قادرًا على اختيار أفضل بنية لخدماتي ، لكل حالة. على سبيل المثال ، في بعض الأحيان أريد مثيلات MariaDB متعددة ، كل منها يخدم تطبيقًا واحدًا. في أوقات أخرى ، أريد مثيل MariaDB واحدًا ، يخدم تطبيقات متعددة. لا أريد أن يخبرني Docker ما هو الأفضل ، أو ما يجب أن أفعله بدلاً من ذلك. يبدو أن Docker دائمًا لديه هذا النوع من الإغراءات ؛).
أعتقد أن أفضل حل هو إقناع Docker بالسماح للحاويات بالإعلان عن البيانات الوصفية التعسفية عن نفسها ، واستخدام هذه الميزة للسماح لـ docker-compose بمعرفة ما إذا كانت الحاوية تعتبر "جاهزة" بحيث يمكن للآخرين الاعتماد عليها.
بالنسبة إلى نهج "تطبيقات db-multi-single" ، أود تعريفًا مثل:

db:
  image: postgres:9.3
  ports:
    - "5432:5432"
app1:
  image: wordpress
  links:
    - db [WP]
app2:
  image: ghost
  links:
    - db [GST]

سيطلق Docker Compose "db" ويسأل عن بياناته الوصفية (ذات الصلة بـ Docker Compose). من ملف yml ، يعرف أن "app1" يتوقع أن يكون "db" "جاهز للعمل على Wordpress" (لا يعني ذلك قبول الاتصالات فحسب ، بل أيضًا مع الكائنات المطلوبة).

ليس لدي حل بسيط لكيفية حل هذا الموقف. أقوم بذلك حاليًا يدويًا ، في خطوتين: صورة مخصصة postgresql-bootstrap ، حيث أقوم بإنشاء db ومستخدم قاعدة البيانات للوصول إليها ؛ وصورة Liquibase-postgresql مخصصة ، لإنشاء كائنات قاعدة البيانات من DDLs التي توفرها (أو المستخرجة من) حاوية Wordpress. عندها فقط يمكنني تشغيل "app1".
يجبرني ذلك على فصل الحاويات في مجموعتي "البنية التحتية" و "التطبيقات" ، إذا كانت حاويات "البنية التحتية" تخدم تطبيقات مختلفة.

يريد Docker Compose أن يكون عديم الجنسية مثل Docker نفسه. لا أعرف ما إذا كان ذلك ممكنًا إذا كان يريد أن يكون مفيدًا حقًا.

+1 للخيار 3

+1

+1 للخيار 3.

+1 للخيار 3

+1 للخيار 3

هذه القضية مطروحة منذ فترة فما الحل؟

@ bweston92 أعتقد أن الوضع هو أن aanand اقترح حلاً في وقت سابق في هذا الموضوع ويبحث عنه

أي مقترحات تصميم بديلة ، إلى جانب المناقشات حول نقاط القوة / الضعف.

أنا شخصياً أعتقد أن الحل المقترح من aanand منطقي للغاية. يبدو واضحًا جدًا بالنسبة لي ، مع كونه مرنًا أيضًا. سيغطي احتياجاتي بعد انتظار فتح منفذ TCP أو الانتظار لفترة زمنية محددة.

حالة الاستخدام الخاصة بي هي فقط للاختبار. ستفشل اختباراتي إذا بدأت قبل إنشاء قاعدة البيانات ، لذلك قمت بتغيير comand الخاص بهم إلى bash -c "sleep 2; python manage.py test --keepdb" ، على النحو التالي:

db:
    image: postgres:9.5
test:
    build: .
    command: bash -c "sleep 2; python manage.py test --keepdb"
    volumes:
        - ./test_project:/app
    links:
        - db
        - selenium
    environment:
        - EXTERNAL_TEST_SERVER=http://testserver:8000/
        - SELENIUM_HOST=http://selenium:4444/wd/hub
selenium:
    image: selenium/standalone-chrome:2.48.2
    links:
        - testserver
testserver:
    build: .
    command: bash -c "sleep 5; python manage.py testserver 8000 --static"
    volumes:
        - ./test_project:/app
    ports:
      - "8000:8000"
    links:
        - db

حتى أتمكن من تشغيل docker-compose run test بدون بدء قاعدة البيانات أولاً والانتظار.

من الصعب تحديد أي قضية هذه الأيام هي المكان "المناسب" للتصويت على وظيفة إنشاء عامل ميناء جديد تسمح بالإعلان عن التبعيات الصريحة ، ولكن اعتبر تصويتي قويًا. مع وظيفة شبكة Docker 1.9 الجديدة ، وإيقاف روابط الحاوية التي تلوح في الأفق لصالحها ، لا توجد الآن طريقة رائعة للتأكد من بدء تشغيل الحاوية A قبل الحاوية B - لأنه إذا كنت تستخدم شبكة Docker 1.9 المعرفة من قبل المستخدم ، فيمكنك لم تعد تحدد روابط الحاوية. هذا ... مكسور.

أنا موافق. هل هناك جدول زمني للحصول على الخيار 3؟ سيكون من الرائع تسريع هذا الأمر.

تجدر الإشارة إلى أن ترتيب التبعية لا يحل هذه المشكلة بالفعل. تنطبق هذه المشكلة على الروابط أيضًا. في كثير من الحالات ، تبدأ الحاوية بسرعة كافية بحيث لا تلاحظ المشكلة ، ولكن المشكلة لا تزال قائمة.

ما هو ضروري لحل هذه المشكلة هو فحص صحي مدرك للتطبيق. الفحص الصحي هو في الأساس حلقة تعيد محاولة بعض العمليات حتى: تنجح العملية ، أو تنتهي المهلة. في حالة خدمة HTTP ، قد يكون هذا هو تقديم طلبات http حتى تحصل على رمز 2xx. بالنسبة لقاعدة البيانات ، قد يكون الاتصال والاختيار من جدول.

مهما كانت الحالة ، فهي خاصة بالتطبيق ، لذا يجب تحديدها من قبل المطور. إذا أردنا تنفيذ الخيار 3 من https://github.com/docker/compose/issues/374#issuecomment -135090543 ، فستظل بحاجة إلى تنفيذ منطق التحقق الصحي هذا.

لقد تم ذكره عدة مرات في هذه المشكلة بالفعل (https://github.com/docker/compose/issues/374#issuecomment-53036154 ، https://github.com/docker/compose/issues/374#issuecomment-71342299 ) ، ولكن لإعادة التكرار ، يمكنك حل هذه المشكلة اليوم بجعل تطبيقك مرنًا للفشل عن طريق إعادة محاولة الاتصال. تحتاج إلى القيام بذلك على أي حال لأي نظام إنتاج.

اتضح أن الوظيفة لجعل تطبيقك مرنًا للفشل هو نفس منطق الفحص الصحي. لذلك ، في كلتا الحالتين ، ما زلت بحاجة إلى تنفيذ نفس المنطق. سيكون الاختلاف الوحيد هو المكان الذي تدرجه فيه. يمكنك الآن تضمينه في التطبيق الخاص بك ، أو في برنامج نصي لنقطة الدخول. من خلال التغيير المقترح ، ستتمكن من تحديده في ملف الإنشاء. في كلتا الحالتين ، لا يزال يتعين عليك تنفيذ فحص صحي لكل خدمة.

هل هناك ميزة كبيرة لتضمينه في ملف الإنشاء بدلاً من البرنامج النصي لنقطة الإدخال؟ ربما لا يزال هذا للنقاش.

العيب الكبير لوضعه في ملف الإنشاء هو أنه يجعل up أبطأ بشكل ملحوظ.

من خلال الشبكة الجديدة ، يمكننا أن نجعل up يحدث بالتوازي (مثلما نفعل مع Stop و rm و scale). يمكن أن تبدأ كل حاوية في وقت واحد ، وإجراء بعض التهيئة ، ثم الانتظار حتى تصبح تبعياتها متاحة للمتابعة. هذا يجعل بدء بيئة سريعة للغاية.

إذا كان يتعين على Compose الانتظار حتى يكتمل الفحص الصحي ، فسيكون بدء التشغيل تسلسليًا بشكل فعال. لا يحدث بدء تشغيل الحاوية وتهيئة التطبيق بالتوازي ، وكل شيء يكون أبطأ.

ستخضع معظم التطبيقات لفحوصات صحية بسبب وجود LB ، ويتم مراقبتها خارجيًا وما إلى ذلك. لفتح تطبيق جديد ليس بالأمر الصعب. لذا ، إذا كان التأليف يدعمه ، فهو خيار يمكن للأشخاص استخدامه. إنه ليس إلزاميًا. في العالم الحقيقي ، يتعين على الأشخاص التعامل مع مجموعة متنوعة من التطبيقات ، وهذه الفكرة القائلة بإمكانية جعل جميع التطبيقات فجأة ذكية غير واقعية وغير عملية. ومنطق الغلاف في نقطة الدخول قبيح فقط. أعتقد أن هناك طلبًا كافيًا في المجتمع على ميزة ما وكما ترى حصل الخيار 3 على الكثير من الأصوات.

مرسل من الايفون الخاص بي

في 18 تشرين الثاني (نوفمبر) 2015 ، الساعة 11:01 صباحًا ، كتب Daniel Nephin [email protected] :

تجدر الإشارة إلى أن ترتيب التبعية لا يحل هذه المشكلة بالفعل. تنطبق هذه المشكلة على الروابط أيضًا. في كثير من الحالات ، تبدأ الحاوية بسرعة كافية بحيث لا تلاحظ المشكلة ، ولكن المشكلة لا تزال قائمة.

ما هو ضروري لحل هذه المشكلة هو فحص صحي مدرك للتطبيق. الفحص الصحي هو في الأساس حلقة تعيد محاولة بعض العمليات حتى: تنجح العملية ، أو تنتهي المهلة. في حالة خدمة HTTP ، قد يكون هذا هو تقديم طلبات http حتى تحصل على رمز 2xx. بالنسبة لقاعدة البيانات ، قد يكون الاتصال والاختيار من جدول.

مهما كانت الحالة ، فهي خاصة بالتطبيق ، لذا يجب تحديدها من قبل المطور. إذا أردنا تنفيذ الخيار 3 من رقم 374 (تعليق) ، فستظل بحاجة إلى تنفيذ منطق التحقق الصحي هذا.

لقد تم ذكره عدة مرات في هذه المشكلة بالفعل (# 374 (تعليق) ، # 374 (تعليق)) ، ولكن لإعادة التكرار ، يمكنك حل هذه المشكلة اليوم بجعل تطبيقك مرنًا للفشل عن طريق إعادة محاولة الاتصال. تحتاج إلى القيام بذلك على أي حال لأي نظام إنتاج.

اتضح أن الوظيفة لجعل تطبيقك مرنًا للفشل هو نفس منطق الفحص الصحي. لذلك ، في كلتا الحالتين ، ما زلت بحاجة إلى تنفيذ نفس المنطق. سيكون الاختلاف الوحيد هو المكان الذي تدرجه فيه. يمكنك الآن تضمينه في التطبيق الخاص بك ، أو في برنامج نصي لنقطة الدخول. من خلال التغيير المقترح ، ستتمكن من تحديده في ملف الإنشاء. في كلتا الحالتين ، لا يزال يتعين عليك تنفيذ فحص صحي لكل خدمة.

هل هناك ميزة كبيرة لتضمينه في ملف الإنشاء بدلاً من البرنامج النصي لنقطة الإدخال؟ ربما لا يزال هذا للنقاش.

العيب الكبير في وضعه في ملف Compose هو أنه يتم تكوينه بشكل أبطأ بشكل ملحوظ.

من خلال الشبكات الجديدة ، يمكننا أن نجعلها تحدث بالتوازي (مثلما نفعل من أجل التوقف ، و rm ، والقياس). يمكن أن تبدأ كل حاوية في وقت واحد ، وإجراء بعض التهيئة ، ثم الانتظار حتى تصبح تبعياتها متاحة للمتابعة. هذا يجعل بدء بيئة سريعة للغاية.

إذا كان يتعين على Compose الانتظار حتى يكتمل الفحص الصحي ، فسيكون بدء التشغيل تسلسليًا بشكل فعال. لا يحدث بدء تشغيل الحاوية وتهيئة التطبيق بالتوازي ، وكل شيء يكون أبطأ.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub.

dnephin النتيجة النهائية هي أن لديك نفس البرامج النصية

بالتأكيد ، سيكون من الرائع حل كل هذا على مستوى التطبيق ولكن في الواقع سيكون لديك فقط التحكم في التطبيق الخاص بك وليس جميع الأجزاء المتحركة الأخرى مثل قاعدة البيانات أو ذاكرة التخزين المؤقت أو قائمة انتظار التدليك.

أتفق مع كل من mbdas و jayfk ،

delfuego : هل يمكنك توضيح كيفية إهمال الروابط ، وخاصة ما يتم استبدالها؟ الارتباط ببعض المستندات / الأمثلة يكفي

@ h17liner : نعم إنه مثير للاهتمام! شكر

بينما أتفق مع dnephin على ذلك

لقد تم ذكره عدة مرات في هذه المشكلة بالفعل ، ولكن لإعادة التكرار ، يمكنك حل هذه المشكلة اليوم عن طريق جعل تطبيقك مرنًا للفشل عن طريق إعادة محاولة الاتصال. تحتاج إلى القيام بذلك على أي حال لأي نظام إنتاج.

لا أرى أن هذا يجعل من شيء مثل إجراء الاختبارات. إذا كنت أقوم فقط باختبار ما إذا كان نموذج ما يتم حفظه بشكل صحيح في تطبيق Django ، فأنا لست متأكدًا من مدى أهمية إضافة المرونة إلى اتصال قاعدة البيانات.

delfuego أعتقد أنك كنت في المكان المناسب أصلاً (# 686) لهذه المشكلة. لا تتعلق هذه المشكلة بالطلب ، إنها تتعلق بالتأخير المصطنع في بدء التشغيل (عند وجود أمر بالفعل). في حين أن هذه الأشياء مرتبطة ، إلا أنها قضايا منفصلة.

أنا لا أوافق على الروابط غير المعتمدة في شبكات الجسر التي أنشأها المستخدم والتي تم توثيقها ليتم إهمالها بشكل عام لا يوجد ترتيب. لذلك ، يعتني الخيار 3 بكل من الطلب ووقت بدء الإصدار.

مرسل من الايفون الخاص بي

في 19 تشرين الثاني (نوفمبر) 2015 ، الساعة 8:14 صباحًا ، كتب Daniel Nephin [email protected] :

delfuego أعتقد أنك كنت في المكان المناسب أصلاً (# 686) لهذه المشكلة. لا تتعلق هذه المشكلة بالطلب ، إنها تتعلق بالتأخير المصطنع في بدء التشغيل (عند وجود أمر بالفعل). في حين أن هذه الأشياء مرتبطة ، إلا أنها قضايا منفصلة.

-
قم بالرد على هذا البريد الإلكتروني مباشرةً أو قم بعرضه على GitHub.

أود أن أقترح الخيار 4 (قد يقول البعض أنه في الواقع صيغة 3)
الحاوية ليست جاهزة حتى تنتهي جميع أوامر بدء التشغيل برمز خروج 0. يجب أن يكون من الممكن تحديد أوامر بدء التشغيل هذه في ملف yml لكل حاوية. يتم تنفيذ هذه الأوامر كما تفعل مع "docker exec" ضد تشغيل الحاوية. فكر في طرق setUp () و tearDown () في اختبار الوحدة الكلاسيكية. نعم ، يمكن أن يكون لدينا أوامر "إيقاف التشغيل" أيضًا.
من الواضح أن الحاوية التالية في التسلسل الهرمي لم يتم إطلاقها حتى تصبح جميع الحاويات التي تعتمد عليها جاهزة.
ملاحظة: شكرًا على DockerCon.Eu الرائع لعام 2015

التوجيه HEALTHCHECK أكثر مرونة (أي يمكن استخدامه في أي وقت لاحق) ومفيد. يجب أن يتم الإعداد داخل البرنامج النصي CMD أو (الأفضل من ذلك) ENTRYPOINT ، تفكيك من خلال معالجة إشارات العملية.

أعتقد أن جوهر المشكلة هنا هو أن الناس يريدون أمرًا واحدًا docker-compose up لإحضار مكدس وكل شيء يعمل بطريقة سحرية.

بناءً على جميع التعليقات ، من الواضح أن هناك العديد من الحلول لحالات الاستخدام المختلفة ولكن لا يوجد "مقاس واحد يناسب الجميع".

يمكنك تنفيذ مهام "التهيئة" بسهولة تامة عن طريق تنفيذ أوامر متعددة لإنشاء عامل الإرساء - وأعتقد أن هذا الأسلوب هو الأسلوب الأكثر عمومية ومرونة.

على سبيل المثال ، قمت بتشغيل دفتر تشغيل Ansible في حاوية "وكيل" بمهمة واحدة تنتظر تشغيل حاوية قاعدة البيانات (MySQL) الخاصة بي على المنفذ 3306. هذه الحاوية "الوكيل" مرتبطة بحاوية "db" الخاصة بي بشكل تلقائي يبدأها عند تنفيذ ما يلي:

$ docker-compose run --rm agent
Creating db_1

PLAY [Probe Host] *************************************************************

TASK: [Set facts] *************************************************************
ok: [localhost]

TASK: [Message] ***************************************************************
ok: [localhost] => {
    "msg": "Probing db:3306 with delay=0s and timeout=180s"
}

TASK: [Waiting for host to respond...] ****************************************
ok: [localhost -> 127.0.0.1]

PLAY RECAP ********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0

بعد ذلك يمكنني تشغيل docker-compose up مع العلم أن حاوية db تعمل بكامل طاقتها.

إليك ملف docker-compose.yml بسيط يدعم هذا:

...
...
db:
  image: mysql
  hostname: db
  expose:
    - "3306"
  environment:
    MYSQL_DATABASE: xxx
    MYSQL_USER: xxx
    MYSQL_PASSWORD: xxx
    MYSQL_ROOT_PASSWORD: xxx

agent:
  image: cloudhotspot/ansible
  links:
    - db
  volumes:
    - ../../ansible/probe:/ansible
  environment:
    PROBE_HOST: "db"
    PROBE_PORT: "3306"

تقوم حاوية "الوكيل" بتشغيل كتاب التشغيل المسمى site.yml في وحدة التخزين المثبتة /ansible الموضحة أدناه:

- name: Probe Host
  hosts: localhost
  connection: local
  gather_facts: no
  tasks: 
    - name: Set facts
      set_fact: 
        probe_host: "{{ lookup('env','PROBE_HOST') }}"
        probe_port: "{{ lookup('env','PROBE_PORT') }}"
        probe_delay: "{{ lookup('env','PROBE_DELAY') | default(0, true) }}"
        probe_timeout: "{{ lookup('env','PROBE_TIMEOUT') | default (180, true) }}"
    - name: Message
      debug: msg="Probing {{ probe_host }}:{{ probe_port }} with delay={{ probe_delay }}s and timeout={{ probe_timeout}}s"
    - name: Waiting for host to respond...
      local_action: >
        wait_for host={{ probe_host }}
        port={{ probe_port }}
        delay={{ probe_delay }}
        timeout={{ probe_timeout }}
      sudo: false

قد يكون أحد الحلول لهدف docker-compose up الوحيد هو تقديم ميزة "سير العمل" لتكوين عامل الإرساء وتضمين ملف مواصفات سير العمل الاختياري الذي يسمح بسيناريوهات تنسيق أكثر تعقيدًا وتحكمًا من خلال تحديد أمر واحد أو أكثر من أوامر Docker-compose "المهام" التي يجب تنفيذها:

# The default workflow, specified tasks will be run before docker-compose up
# The "up" task is implicit and automatically invoked for the default workflow
# The "up" task is explicit for custom workflows as some workflows may not want docker-compose up
default:
  tasks:
    - run --rm agent
    - up

# Custom workflows that can be invoked via a new docker-compose command option
# This example:
# 1. Runs agent container that waits until database container is up on port 3306
# 2. Runs Django database migrations from app container
# 3. Runs Django collect static task from app container
# 4. Runs test container that runs acceptance tests against linked app container
# Does not execute a docker-compose up afterwards

test:
  tasks:
    - run --rm agent 
    - run --rm app manage.py migrate
    - run --rm app manage.py collectstatic --noinput
    - run --rm test

اليوم أحقق ما سبق باستخدام Makefiles ، والتي توفر قدرة أعلى على تحديد سير العمل الخاص بي لسيناريوهات مختلفة.

سيكون من الرائع أن يتم إدخال ميزة "سير العمل" أو ما شابه ذلك في تكوين عامل الإرساء ، مما يوفر حلاً عامًا ومرنًا جدًا لهذه المشكلة بالذات وغيرها الكثير.

متفق عليه ، المشكلة هي أن الناس يتوقعون أن يكون تكوين عامل النقل كافياً لعمليات نشر الإنتاج. شخصياً ، أعتقد أنه سيمر وقت طويل قبل أن يصبح ذلك ممكنًا ويبدو أن Helm أقرب كثيرًا إلى هذا الهدف.

olalonde ، من المؤكد أننا نحب التأليف ليكون جاهزًا للإنتاج ... لكننا سنأخذه لدعم الوظائف المهمة والحالية التي ، نظرًا لإيقاف روابط الحاوية ، ستختفي ما لم يتم نسخها إلى المستخدم الجديد - نموذج الشبكات المنشأة. (مرة أخرى ، ربما لا يتوافق هذا الطلب تمامًا مع هذه المشكلة المحددة - لا يزال من غير الواضح بالنسبة لي ما إذا كان مجرد الحصول على طلب بدء تشغيل الحاوية "ينتمي" هنا أم في المشكلة رقم 686 ...)

باستخدام توجيه HEALTCHECK Docker ، يمكن لوظيفة depends_on إما انتظار بدء تشغيل الحاوية (بدون فحص صحي) أو إنهاء البرنامج النصي healthcheck بنجاح (رمز الخروج 0 ). هذا مرن بقدر ما يحصل (يمكنك تحديد المنطق التعسفي) ويحافظ على منطق healthcheck حيث ينتمي (داخل الحاوية التي يتم فحصها).

delfuego حتى بالنسبة للتطوير والاختبار ، ستكون هذه الوظيفة مفيدة. أنا شخصياً أريد أن أكون قادرًا على القيام بـ docker-compose run test وجعلها تعمل دون تقديم الخدمات مسبقًا والانتظار يدويًا. على الرغم من أن هذا ممكن ، إلا أنه يجعل البدء في المشروع أكثر إيلامًا ويضيف المزيد من الطرق التي يمكن أن يفشل بها الاختبار.

+1

أعتقد أن الحل يتطلب طريقة وسطية - لن تتمكن عملية الإنشاء مطلقًا من تفسير جميع الطرق المختلفة التي يمكن من خلالها اعتبار التطبيقات متاحة أم لا. ستعني فكرة الفحص الصحي أشياء مختلفة لأشخاص مختلفين ، وقد لا تكون بسيطة مثل "هل هو صالح أم لا". في الإنتاج ، قد تقوم بإزالة الحاوية إذا كانت تعرض أوقات استجابة طويلة بشكل غير عادي ، حتى لو كانت تجتاز أي اختبارات HTTP.

لذلك أشعر أن الدعم الأساسي لاستجابات HTTP أو المنافذ المفتوحة أو الملفات التي تم إنشاؤها أو خطوط السجل المنبعثة يجب أن يكون كافياً للتطوير. أي شيء أكثر تقدمًا من ذلك يصبح على الفور تقريبًا خاصًا بالتطبيق. أحب أيضًا فكرة تشجيع المطورين على جعل الأجزاء الفردية لمكدسات تطبيقاتهم أكثر قوة.

شكرًا pugnascotia ، هذا تعليق بناء ، ونهج معقول ("أفضل ما في العالمين"؟)

لا يبدو أن الحلول التي تمت مناقشتها حاليًا تتناول في الواقع مشكلة _original_egypt التي تعتبر أبسط بكثير ... والتي لا تنتظر توفر الخدمة ، ولكن انتظار الخدمة حتى الخروج.

لدي حالة استخدام حيث لدي حاويتان تعرضان نفس المنافذ. أول تشغيل لمدة 15-60 ثانية ، ثم يخرج. ثم يجب أن تبدأ الخدمة الثانية. لا توجد طريقة (واضحة؟) للقيام بذلك في إنشاء اليوم لأنه سيكتشف تعارض المنفذ وسيخرج ؛ ولا حتى "إعادة التشغيل: دائمًا" هو الحل.

نعم ، لم يتم تصميم Compose لحالة الاستخدام هذه. يركز التأليف على بيئات وقت التشغيل ، وليس بناء خطوط الأنابيب. لا أعتقد أن هذا هو موضوع المشكلة الأصلية المبلغ عنها.

كان هناك عدد قليل من الطلبات للحصول على المزيد من الميزات الموجهة نحو البناء ، لكنني لا أعتقد أنها منطقية للتأليف. الوظيفتان مختلفتان تمامًا ومحاولة جعلهما مناسبين لنفس تنسيق التكوين من المحتمل أن يؤدي إلى الكثير من الالتباسات وتجربة مستخدم سيئة.

ewindisch يمكن تعميم حالة الاستخدام الخاصة بك لتشغيل سلسلة من الوظائف

يغطي هذا الجزء من وثائق Compose السؤال عن سبب عدم توفر هذه الإمكانية في Compose:

https://docs.docker.com/compose/faq/#how -do-i-get-compose-to-wait-for-my-database-to-be-ready-before-start-my-application

لكن هذه الصفحات لا تذكر المشكلة على الإطلاق:

https://docs.docker.com/compose/django/
https://docs.docker.com/compose/rails/
https://docs.docker.com/compose/wordpress/

على الأقل ، يجب أن تتضمن هذه الصفحات إقرارًا بأن Compose لن ينتظر حتى تكون حاوية قاعدة البيانات جاهزة. يمكنهم أيضًا تضمين أمثلة على طرق التعامل معها.

ewindisch في الواقع ، هذا هو بالضبط ما كنت أقترحه في https://github.com/docker/compose/issues/374#issuecomment -126312313 - مع فرضية أن حل _that_ المشكلة يمنح المستخدمين أيضًا الأدوات اللازمة لحل مشكلة طلب بدء التشغيل ( إن لم يكن مشكلة المرونة طويلة المدى).

ما زلت مهتمًا باستكشاف مساحة الحل هذه ، إذا كان أي شخص آخر كذلك.

انا.

أنا أيضا.

+1

+3

+1

التصويت الإيجابي على نطاق واسع!
يؤثر هذا حاليًا على استخدام الأدوات التي يتم تشغيلها في الحاوية ، ولكنها تعتمد على أحداث عامل الإرساء (مثل jwilder / nginx-proxy). الطريقة التي أقوم بها هي مجرد عامل عامل تشغيل - يقوم بتكوين المستمع يدويًا وتشغيل جميع الحاويات الأخرى بعد ذلك (مما يفسد كل جمال عامل الميناء - يؤلف كنقطة دخول واحدة).

meetmatt هل حاولت تشغيل وكيل jwilder / nginx بعد ذلك؟ لا ينبغي أن يكون ترتيب البدء مهمًا لذلك ، فسوف يلتقط الحاويات الموجودة (قيد التشغيل) عند البدء

+1

+1

أود حقًا أن أرى حلًا شفافًا يعتمد على القناة. في الأساس مثل libchan. بهذه الطريقة ، إذا قمت بالاستعلام عن قاعدة بيانات ، فسيتم تخزين الطلب مؤقتًا حتى تصبح قاعدة البيانات جاهزة.

لا أعتقد حقًا أن ترتيب التحميل هو حل كافٍ في الأنظمة الموزعة. ماذا لو احتجت ، على سبيل المثال ، إلى إعادة تشغيل قاعدة البيانات ولكن الخدمات الأخرى قد تتعطل نتيجة لذلك؟ الحل الحقيقي من شأنه التعامل مع حالة الاستخدام هذه أيضًا.

عد لي ، حيث أن القدرة على التنبؤ بخط أنابيب التنفيذ هي أمر أساسي لما نقوم به في العمل. +1

+1

لابد أنني أفتقد شيء ما.

لماذا لا يؤيد أحد إضافة "الانتظار حتى" في تشغيل عامل الإرساء (محرك الرصيف نفسه). في جميع الحالات التي يمكنني التفكير فيها ، تعرف الحاوية التابعة متى تكون "جاهزة" لكن عامل الإرساء لا يحترم ذلك.

في الحالة الأصلية (تحميل mysql لمجموعة كبيرة من البيانات وفي الهواء الطلق) ، يمكن لحاوية mysql العودة أو الإشارة عندما تكون جاهزة ولن تبدأ الحاوية في الهواء الطلق حتى ذلك الحين.

أرغب في تشغيل منطق وإشارة تعسفي إلى عامل الإرساء عندما أكون جاهزًا وفقًا لما قررته (على سبيل المثال عندما تظهر رسالة معينة في السجل -> إشارة CONTAINER_UP).

net: "container:[name or id]" لماذا لا أطلب بدء تشغيل الحاويات الخاصة بي؟ اضطررت إلى إسقاط links لأنه سيتم إهماله وأريد أن يستخدم المكدس بالكامل net: "host" للشبكات. للأسف هذا غير مسموح به مع links . هل هناك طريقة أخرى لتغيير ترتيب التمهيد للحاويات أو يجب علي مشاركة وحدات تخزين عديمة الفائدة بينها؟

تحديث:

لقد أجريت للتو إعادة الطلب بأحجام عديمة الفائدة بدلاً من links :

base:
  build: ./base
  net: "host"
  volumes:
    - /root/lemp_base
phpmyadmin:
  build: ./phpmyadmin
  net: "host"
  volumes_from:
    - base
  volumes:
    - /root/lemp_phpmyadmin
ffmpeg:
  build: ./ffmpeg
  net: "host"
  volumes_from:
    - phpmyadmin
  volumes:
    - /root/lemp_ffmpeg
mariadb:
  build: ./mariadb
  net: "host"
  volumes_from:
    - ffmpeg
  volumes:
    - /root/lemp_mariadb
php:
  build: ./php
  net: "host"
  volumes_from:
    - mariadb
  volumes:
    - /root/lemp_php
nginx:
  build: ./nginx
  net: "host"
  volumes_from:
    - php
  volumes:
    - /root/lemp_nginx

(لقد قمت بمسح وحدات التخزين المشتركة الأخرى من المكدس ومعلومات أخرى مثل اسم الحاوية والمنافذ لتبدو بسيطة.)

إذا كنت أرغب في الاستخدام مع net: "container:base ، فقد تلقيت رسالة خطأ في الأمر docker-compose build .

ERROR: Service "mariadb" is trying to use the network of "lemp_base", which is not the name of a service or container.

ما لا يعجبني في هذا الحل هو أن كل حاوية أخرى ستحصل على ملفات خادم الويب في مجلد /var/www من base .

تعديل:
لسبب ما ، يقوم هذا المكدس بحذف المجلد /var/www بأكمله عند بدء التشغيل.

رأيي المتواضع هو أن أي آلية تنتهي بـ Docker Compose مع العلم بالتبعية بين الحاوية تتعارض مع فصل المخاوف. يعتبر Docker Compose مسؤولاً عن تشغيل الحاويات A و B. الحاويات A و B مسؤولة عن خدماتها الخاصة. إذا كان B يعتمد على A للعمل بشكل صحيح ، فمن مسؤولية B الانتظار حتى يكون A في حالة صالحة للعمل. كما قيل في المناقشة ، يمكن القيام بذلك من خلال المهلة أو إعادة المحاولة أو أي شيء آخر ، ولكن هذه مشكلة B ، وليست Docker Compose ولا A. SoC ذات أهمية قصوى لاستقلالية الخدمة والقياس المناسب.

هل هناك اي عمل على فكرتك 3aanand ؟ سيكون من الجيد معرفة ما إذا كان هناك أي تقدم ، فقد بدا الأمر وكأنه بداية واعدة من شأنها أن تساعد في بعض حالات الاستخدام الشائعة جدًا حتى لو لم تكن حلاً مثاليًا

+1

+1

ربما أكون مخطئًا ولكن args: buildno: يمكنه طلب الحاويات في docker-compose.yml الإصدار 2؟

أميل إلى الموافقة على أن هذا مصدر قلق لا ينتمي إلى Compose. حصلت Dockerize الممتازة فيjwilder على دعم لانتظار الحاويات التابعة ويمكنك تحديد البروتوكول / المنفذ الذي تنتظره. أود أن أقترح أن هذا يناسب معظم حالات الاستخدام الموضحة هنا:

api:
  build: .
  ports:
   - "8000:80"
  expose:
  - "80"

test:
  build: test
  command: dockerize -wait http://api:80 -wait tcp://db:5432 somecommand -some arg -another arg2
  links:
    - api:api

من الناحية المثالية ، نستخدم Docker Events API لاكتشاف ذلك تلقائيًا ، ولكن هذا يعني أن كل حاوية ستحتاج أيضًا إلى الوصول إلى وقت تشغيل Docker الذي ربما لا يكون ممكنًا / شيء نريده.

أعتقد أنه يجب أن يتم الانتظار خارج الإنشاء. في مطوري ، سأستخدم هجينًا لما اقترحه timercheck.io . أنا الشيء الذي سيمنحني بالضبط ما أحتاجه دون التسرع في استخدام RabbitMQ أو شيء مشابه.

نحن نستخدم نقطة إدخال البرنامج النصي shell التي تنتظر المنفذ المفتوح ، مع مهلة 15 ثانية:

#!/usr/bin/env bash

# wait for db to come up before starting tests, as shown in https://github.com/docker/compose/issues/374#issuecomment-126312313
# uses bash instead of netcat, because netcat is less likely to be installed
# strategy from http://superuser.com/a/806331/98716
set -e

echoerr() { echo "$@" 1>&2; }

echoerr wait-for-db: waiting for db:5432

timeout 15 bash <<EOT
while ! (echo > /dev/tcp/db/5432) >/dev/null 2>&1;
    do sleep 1;
done;
EOT
RESULT=$?

if [ $RESULT -eq 0 ]; then
  # sleep another second for so that we don't get a "the database system is starting up" error
  sleep 1
  echoerr wait-for-db: done
else
  echoerr wait-for-db: timeout out after 15 seconds waiting for db:5432
fi

exec "$@"

يجب حل هذا من خلال (ويبدو أنه وشيكًا مع تحديث المستندات) depend_on ، نعم؟

لا. depends_on يطلب فقط. لتأخير بدء حاوية أخرى فعليًا ، يجب أن تكون هناك طريقة ما لاكتشاف متى تنتهي العملية من تهيئة نفسها.

اه، شكرا على التوضيح. =)

لقد قمت بكتابة أداة سطر أوامر bash نقية تسمى wait-for-it والتي يمكن تضمينها في عمليات نشر docker للمساعدة في مزامنة عمليات نشر الخدمة.

بالنسبة لي ، ليس من الجيد إجراء كود ثابت لمجموعة عشوائية من "فحوصات التوفر". هناك العديد من المواقف الخاصة بنوع واحد من النشر ولا يمكنك تغطيتها جميعًا. كمثال ، في التطبيق متعدد الحاويات ، أحتاج إلى الانتظار حتى تظهر رسالة سجل معينة في ملف سجل معين - عندها فقط ستكون خدمة الحاوية جاهزة.
بدلاً من ذلك ، ما نحتاجه هو SPI يمكنني تنفيذه. إذا قدم Docker بعض الأمثلة على التطبيقات لحالات الاستخدام الأكثر شيوعًا (مثل TCP connect) ، فلا بأس بذلك. ولكن يجب أن تكون هناك طريقة بالنسبة لي لتوصيل وظائفي وجعل Docker يطلق عليها.
يعد Docker Compose عديم الفائدة إلى حد كبير بالنسبة لي كمنتج كامل ، إذا لم أتمكن من تشغيل حاوياتي وتشغيلها بشكل موثوق. لذلك هناك حاجة إلى "SPI جاهزية لخدمة الحاوية" ثابتة وموحدة. ويجب ألا تكون كلمة "جاهز" منطقية ، حيث من المحتمل أن يكون هناك المزيد من مستويات الاستعداد (مثل: "الآن يمكنك القراءة" و "الآن يمكنك الكتابة").

realulim جيد الكتابة. أتفق تمامًا مع فكرة السماح لنا بتحديد ما تعنيه حالة الخدمة "جاهزة" عبر المكونات الإضافية. أعتقد أيضًا أنه من الجيد أن يكون لديك افتراضي للمكوِّن الإضافي الذي يتحقق فقط من أن الخدمة تستمع إلى اتصال http / tcp. سيغطي ذلك غالبية الحالات هناك.

هذا ما توصلت إليه ، في ملف الإدخال ؛

until netcat -z -w 2 database 5432; do sleep 1; done
# do the job here, database host on port 5432 accepts connections

@ kulbida ،
أفعل شيئًا مشابهًا جدًا مع MySQL. "قاعدة البيانات" في هذه الحالة هي ارتباط في ملف الإنشاء.

if [[ "$APP_ENV" == "local" ]]; then
    while ! mysqladmin ping -h database --silent; do
        sleep 1
    done
    # Load in the schema or whatever else is needed here.
fi

كانت هناك بعض التعليقات في سلسلة الرسائل هذه والتي تدعي أن طلب بدء التشغيل ليس سوى مجموعة فرعية من استرداد أخطاء مستوى التطبيق ، والتي يجب أن يتعامل معها تطبيقك على أي حال. أود أن أقدم مثالاً واحدًا لأوضح أين قد لا يكون هذا هو الحال دائمًا. ضع في اعتبارك ما إذا كانت بعض الخدمات تعتمد على قاعدة بيانات مجمعة ، وكلما ضاع النصاب بسبب تعطل وما إلى ذلك ، فأنت لا تريد إعادة المحاولة تلقائيًا من التطبيق. قد يكون هذا هو الحال على سبيل المثال إذا تطلب استرداد قاعدة البيانات بعض الخطوات اليدوية ، وتحتاج إلى أن تظل الخدمات معطلة بشكل لا لبس فيه حتى يتم تنفيذ هذه الخطوات.

الآن قد يكون منطق معالجة أخطاء التطبيق مختلفًا تمامًا عن منطق بدء التشغيل:

  • إذا كان db معطلاً لأننا بدأنا للتو ، فانتظر حتى يصبح متاحًا.
  • إذا كان db معطلاً بسبب تعطله ، فقم بتسجيل خطأ فادح وتموت.

قد لا يكون هذا هو السيناريو الأكثر شيوعًا ، لكنك ترى هذا النمط أحيانًا. في هذه الحالة ، يتم استخدام التجميع لحل مشكلة "الشبكة غير موثوقة" في الحالة العامة ، مما يغير بعض التوقعات حول شروط الخطأ التي يجب إعادة محاولة تطبيقها في التطبيق. يمكن أن تكون أعطال الكتلة نادرة بدرجة كافية ، ويمكن أن تكون إعادة تشغيلها تلقائيًا محفوفة بالمخاطر بدرجة كافية ، حيث يُفضل إعادة تشغيل الخدمات يدويًا على إعادة المحاولة في التطبيق. أظن أن هناك سيناريوهات أخرى أيضًا قد تتحدى الافتراضات حول وقت إعادة المحاولة.

بشكل عام ، أنا أدعي أن طلب بدء التشغيل ومعالجة الأخطاء ليسا متكافئين دائمًا ، وأنه من المناسب لإطار عمل توفير ميزات (اختيارية) لإدارة أمر بدء التشغيل. أتساءل ما إذا كان هذا ينتمي إلى عامل ميناء ، على الرغم من ، بدلاً من التأليف. قد تكون هناك حاجة إليه في أي وقت يتم فيه بدء تشغيل عامل الإرساء ، بغض النظر عما إذا تم استخدام عملية الإنشاء.

هناك مناقشة تبدأ في الريبو لمحرك الرصيف في الاقتراح https://github.com/docker/docker/issues/21142 لإضافة دعم للفحص الصحي. بمجرد توفر هذا الدعم ، سيكون من الممكن لـ Compose توفير طريقة لتكوينه ، واستخدامه لبدء التشغيل المتأخر.

ماذا عن استخدام نظام الملفات للتحقق من وجود ملف؟

ready_on: /tmp/this_container_is_up_and_ready

بهذه الطريقة ، يعود الأمر إلى مطور الحاوية ليقرر متى تسير الأمور ، ولكن يمكن أن ينتظر الإنشاء حتى تعلن الحاوية أنها جاهزة. إنها اتفاقية صريحة ، ولكن يمكن إضافتها بسهولة كطبقة إضافية للصور التي ليس لها هذا السلوك ..

سيكون الدعم المدمج للفحوصات الصحية جيدًا ؛ في هذه الأثناء ، ها هو الاختراق الذي عملت به في إعداد إنشاء عامل الإرساء المحلي:

    nginx:
        image: nginx:latest
        command: /bin/bash -c "sleep 2 && echo starting && nginx -g 'daemon off;'"
        ...

(في الإنتاج ، وكلاء التطبيق الخاص بي إلى عدد قليل من الخوادم الأولية التي تعمل بالفعل باستخدام proxy_pass ؛ في التطوير والاختبار المحلي ، أبدأ مثيلات docker من هذه ، ويحتاج nginx إلى الانتظار قليلاً حتى يبدأوا ، وإلا فإنه تعطل وتموت. يحافظ الشيء daemon off على nginx في عملية واحدة ، وإلا فإن عامل الإرساء سيوقف الحاوية بمجرد أن تنتج العملية الرئيسية التابعة لها.)

فقط لإضافة سنتي ، إذا كنت تستخدم أداة إنشاء ANT ، فإنها تأتي مع دعم مدمج لتأخير التنفيذ حتى يتم فتح مقبس معين.

يقوم خادم Jenkins CI الخاص بنا بتدوير حاويات المشروع باستخدام Docker Compose ثم تشغيل ANT من داخل الحاوية الرئيسية ، مثل هذا:

docker-compose up -d
docker exec -it projectx-fpm-jenkins ant -f /var/www/projectX/build.xml

هذا هو جزء التكوين المناسب من ملف docker-compose.yml. لاحظ أنه ، كما نوقش أعلاه ، جعل fpm يعتمد على mysql لا يكفي لضمان أن تكون خدمة MySQL جاهزة عند الحاجة إليها بالفعل.

version: '2'
services:
  nginx:
    build: ./docker/nginx
    depends_on:
      - fpm
  fpm:
    build: ./docker/fpm
    depends_on:
      - mysql
  mysql:
    image: mysql:5.7
    environment:
      - MYSQL_ROOT_PASSWORD=projectx
      - MYSQL_DATABASE=projectx

ولكن يمكنك الانتظار أثناء مهمة ANT:

<!-- other targets... -->

<target name="setup db">
    <!-- wait until the 3306 TCP port in the "mysql" host is open -->
    <waitfor>
        <socket server="mysql" port="3306"/>
    </waitfor>

    <exec executable="php">
        <arg value="${consoledir}/console"/>
        <arg value="doctrine:database:create"/>
        <arg value="--no-interaction"/>
    </exec>
</target>

kulbida هذا فعل الحيلة ، شكرا. شيء أسرع قليلاً:

while ! nc -w 1 -z db 5432; do sleep 0.1; done

_depends_on_ قد يحل المشكلة.
من وثائق عامل الميناء .
التعبير عن التبعية بين الخدمات ، والتي لها تأثيران:

  1. سيبدأ عامل الإرساء إنشاء الخدمات بترتيب التبعية. في المثال التالي ، سيتم بدء db و redis قبل الويب.
  2. ستتضمن خدمة إنشاء عامل الإرساء تبعيات SERVICE تلقائيًا. في المثال التالي ، سيقوم عامل إنشاء شبكة الويب بإنشاء وبدء db و redis.

الإصدار 2'
خدمات:
الويب:
بناء:.
يعتمد على:
- ديسيبل
- ريديس
ريديس:
الصورة: redis
ديسيبل:
الصورة: postgres

alexch : في اختبار أداء جانب العميل (خدمة مصغرة موجهة عبر nginx +). اختبار nginx المُرسى - كان الانخفاض في الحمل من أعلى المستويات إلى ما يقرب من الصفر منخفضًا يتكرر كل 1-2 دقيقة. قررت أخيرًا استخدام Nginx غير المُرسى الذي يعمل كجهاز افتراضي (فقط بسبب الاختلاف الهائل في الأداء) ، ربما مشكلة مكون إضافي لبرنامج تشغيل الشبكة / libNetwork.

يبدو أنsyamsathyan depends_on لا يساعد.

skorokithakis ، kulbida هذا حل جميل. للأسف ، لا يتوفر netcat افتراضيًا في أي من الخدمات التي أحتاجها للاتصال بقاعدة البيانات الخاصة بي (بما في ذلك postgres ). هل تعرف أي طريقة بديلة؟

nottrobin لا أخشى ، لقد قمت للتو بتثبيته في صورتي: /

nottrobin يعمل فريقي على هذا ،

بالنسبة لأولئك الذين لديهم باش مؤخرًا ، هناك حل خالٍ من netcat (مستوحى من: http://stackoverflow.com/a/19866239/1581069):

while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/db/5432'; do sleep 0.1; done

أو نسخة مطولة أقل:

while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/db/5432' >/dev/null 2>/dev/null; do sleep 0.1; done

typekpb الذي يعمل بشكل مثالي. شكر!

الآن بعد أن تم دمج دعم HEALTHCHECK عند المنبع وفقًا لـ https://github.com/docker/docker/pull/23218 - يمكن اعتبار ذلك لتحديد متى تكون الحاوية سليمة قبل البدء في الترتيب التالي. تم حل نصف اللغز :)

الآن بعد أن تم دمج دعم HEALTHCHECK في اتجاه المنبع وفقًا لرسو / عامل إرساء رقم 23218 - يمكن اعتبار ذلك لتحديد متى تكون الحاوية سليمة قبل بدء التشغيل التالي في الترتيب. تم حل نصف اللغز :)

تبدو جيدا. كيف يتم تنفيذه على docker-compose.yml ؟

تبدو جيدا. كيفية تنفيذه على docker-compose.yml؟

سيكون الجزء الآخر من اللغز عبارة عن ساعة إنشاء عامل ميناء للحاويات الصحية ، واستخدام شيء مثل بناء جملة يعتمد على المذكور أعلاه في هذه المسألة. سيتطلب تصحيحات لتكوين عامل الإرساء حتى تعمل الأشياء.

لاحظ أيضًا أن ميزة الفحص الصحي في Docker لم يتم إصدارها حاليًا ، لذلك ربما تحتاج إلى التوافق مع دورة إصدار Docker / Docker Compose.

لقد كتبت مكتبة js بها طريقة .waitForPort() . تمامًا كما تم ذكره من قبل ، قد لا يعمل هذا في جميع المواقف ، ولكن يمكن أن يكون جيدًا في غالبية حالات الاستخدام.
انظر مدونتي .

دمج HEALTHCHECK هو خبر سار.

في غضون ذلك ، يصف هذا المستند المشكلة وبعض الحلول.

pablofmorales كلا ، لأن depends_on يتحقق فقط من أن الحاوية جاهزة .

تحتاج بعض الشياطين إلى بعض الوقت الإضافي لتشغيل أنفسهم والبدء في الاستماع إلى المنافذ والعناوين المخصصة لهم ، وأبرزها MySQL.

ما زلت أفكر في إعلان "READY_ON" لا يزال الأفضل بشكل عام. إنه يترك القرار بشأن متى يكون شيء ما جاهزًا للحاوية نفسها ، بغض النظر عن الصورة ، فهو واضح في الاشتراك وتضمن وظيفة مسار الموارد (داخل الحاوية) في Docker Remote API الحد الأدنى من التغييرات المطلوبة.

السلوك عندما تكون الحاوية "فوق" هو ​​التأثير الوحيد الذي يجب أن يحدث. سيتم الإبلاغ عن "up" فقط عندما يكون الملف READY_ON موجودًا.

أعتقد أن هذا يمثل 90٪ من السلوك الذي كان الجميع يناقشه. أعتقد أن "healthcheck" هنا يتم الخلط بينه وبين حدثين مختلفين ، لكن محاولة حصره في حدث واحد. أحدهما "جاهز" لسلسلة الأحداث عند تدوير البنية التحتية ، والآخر هو "الصحة" بحيث يمكن الحفاظ على البنية التحتية.

"جاهز" هو المكان المناسب تمامًا لمساعدة عامل الرصيف. بالنسبة إلى "الصحة" ، فهي متنوعة جدًا من حيث الأنظمة ، وأعتقد أن الأمر متروك للحاوية للتعامل مع ذلك.

للحصول على بديل أفضل لفحص الصحة ، قد ترغب في النظر إلى شيء مثل طيار الحاويات الذي لا يغطي الصحة فحسب ، بل يشمل اكتشاف الخدمة ومراقبتها أيضًا. https://github.com/joyent/containerpilot

نعم ، هذا تمييز دقيق ومهم. ومع ذلك ، كيف ستكتب الحاويات هذا الملف دون أن تصبح الصور أكثر تعقيدًا؟ يبدو لي أنه سيتطلب برنامج نصي مجمّع لكل حاوية واحدة تريد استخدام هذا.

حسنًا ، سيتعين عليك بدء تشغيل برنامج نصي لتهيئة المثيل على أي حال ... آخر شيء يحتاجه البرنامج النصي إلى القيام به هو لمس ملف. بالنسبة لي ، يبدو هذا أسهل بكثير من محاولة تشغيل مدير تنفيذي على جهاز بعيد لإجراء فحص صحي. على الأقل باستخدام ملف يعمل باللمس ، يمكن مشاهدته ، وما إلى ذلك تمامًا عبر واجهة برمجة التطبيقات بشكل سلبي دون الحاجة إلى إدخال سياق الحاوية.

أوافق على ذلك ، لكن العديد من الحاويات لا تستخدم نصًا برمجيًا ، فهي تقوم فقط بتثبيت خدمة مثل Postgres أو Redis وتتركها تبدأ دون مشاهدتها.

في حالتي ، أنا أستخدم بوابة Kong API

قبل تشغيل حاوية kong ، تحقق مما إذا كانت Cassandra تعمل مع هذا البرنامج النصي

while true; do
    CHECK=`kong-database/check`
    if [[ $CHECK =~ "system.dateof" ]]; then
        break
    fi
    sleep 1;
done

ملف الشيك يحتوي على هذا

#!/bin/bash
docker cp cassandra-checker kong-database:/root/
docker exec -i kong-database cqlsh -f /root/cassandra-checker

كاساندرا مدقق هو مجرد استعلام بسيط

SELECT dateof(now()) FROM system.local ;

بالتأكيد ، لكن البديل هو فحص صحي ، والذي يتطلب نصًا يتعين عليك كتابته على أي حال ، لذلك لا يوجد فرق في النفقات العامة. إنه أيضًا اشتراك صريح ، مما يعني أنك تعلن أنك تريد هذا السلوك. أما بالنسبة لشيء لا يقوم بتشغيل برنامج نصي ، فيمكنك دائمًا أن يكون لديك مسار جاهز للتحقق من ملف pid أو مقبس unix ؛ الذي لا يتطلب نصًا.

هذا صحيح ، أنت على حق.

قد يكون التحقق من وجود ملف أمرًا جيدًا في الكثير من الحالات ، ولكن إجبار الحاويات على استخدام برنامج نصي لبدء التشغيل عندما لا يحتاجون إلى أحد الملفات بطريقة أخرى يعد أمرًا مزعجًا. لماذا لا يكون هناك أيضًا فحوصات لشروط أخرى بسيطة للغاية؟ سيكون من المفيد بشكل خاص الانتظار حتى يتم الاستماع إلى العملية على منفذ tcp معين.

تم قبول هذه الفكرة ، لذلك ليس هناك أي تأثير على أي شيء. Infact أنت صريح في قول ما ينبغي توقعه.

قد لا يكون الاستماع إلى منفذ tcp كافيًا لمعرفة وقت تهيئة الحاوية حيث قد تكون هناك مجموعة من بيانات الإعداد التي تحتاج إلى تشغيل. الجحيم ، إذا قمت بالاتصال بحاوية postgres بسرعة كبيرة ، حتى عبر tcp ، فستتلقى خطأ يفيد بأن db ليس جاهزًا بعد.

إذا كنت أفهمك بشكل صحيح ، فهذا يعني "الاشتراك ، وإلا فلن تتمكن من استخدام هذه الميزة". Ergo ، إذا كنت بحاجة إلى هذه الميزة ولا يستخدم تطبيقي ملف pid ، فأنا مجبر على استخدام برنامج نصي لبدء التشغيل.

بالنسبة لـ MySQL (حالة OP) ، بمجرد الاستماع ، تصبح جاهزة. إنهم يواجهون الكثير من المتاعب للتأكد من صحة ذلك ، ربما في حالات مثل هذه الحالة. رأيي هو أنه من المحتمل أن تكون هناك قائمة مختصرة من الشروط التي يمكن تعدادها بحيث يمكنك "الاشتراك" لتهيئة فحص جاهز مقابل أي من هذه الشروط. لا أرى أي سبب لضرورة القيام بذلك بطريقة واحدة فقط.

بالنسبة لـ mysql ، بمجرد أن تستمع ، لا تكون جاهزة. في حالة العقدة الواحدة البسيطة ، ستكون جاهزة ، ولكن إذا كان لديك أكثر من عقدة واحدة ، فمن المؤكد أنها لن تكون جاهزة بعد. أفهم ما تقصده بعبارة "طريقة واحدة فقط" ، لكنني أعتقد أنها مثالية تمامًا كتجريد أساسي. أرى أنه أكثر مكانًا حيث يمكنك تطبيق أي أدوات تريدها. هيك ، يمكن للبرنامج النصي الخاص بك التواصل مع الخدمات الخارجية وجعلهم يتحققون من الحاوية ، وفي هذه الحالة قد تشير خدماتك الخارجية إلى وكيل الحاوية لكتابة الملف. المرونة مع قدم.

إذا حاولت القيام بأي شيء في قائمة "الشروط" هذه ، فستكون هناك دائمًا حالة لا تعمل فيها. ومع ذلك ، سيعمل لمس الملف دائمًا ، نظرًا لأن الصورة تعرف متى تعتقد أنها جاهزة (أوه ، لا بد لي من الانتظار على مضيفين آخرين ، أحتاج إلى تنزيل الملفات ، أحتاج إلى التأكد من توفر خدمة $ external_service أيضًا ، سأمتد بشكل صحيح ، لكن لسبب ما لا أمتلك الأذونات الصحيحة لقاعدة البيانات ، لماذا هذه الصورة للقراءة فقط ... إلخ.

هذه الأنواع من البرامج النصية موجودة بالفعل في كل مكان ... الجحيم ، لقد كان من الضروري بالفعل كتابة هذه البرامج النصية لأننا لم يكن لدينا وظائف مثل هذه من قبل. لذا فإن وضع نص مثل هذا هو الحد الأدنى ، لأنه من المحتمل أن يكون هناك نص موجود بالفعل.

هناك حالة أخرى محتملة ، وهي أن يكون لديك شيء مثل رئيس الطهاة أو ansible يعمل ضد هذا المضيف ثم كتابة الملف.

إذا كانت مسألة فحص جانب Docker ، فهناك شيء مثل ؛

UPCHECK --port=7474 --interval=0.5s --response="Please log in"

بالنسبة للسجل ، أعتقد أن حل الملف يتمتع بالكثير من المزايا ، ولكنه يقدم أيضًا تعقيدًا.
80٪ من الوقت ، سيعمل التحقق من استجابة برنامج التعاون الفني بشكل جيد.

حسنًا ... أفترض:

UPCHECK --file=/tmp/container_is_ready --interval=0.5s --timeout=2m

هو مجرد نفس الشيء.

أنا أعمل بالفعل على إعادة تنفيذ تكوين عامل الإرساء الذي يضيف وظائف لانتظار ظروف معينة. يستخدم libcompose (لذلك لا يتعين علي إعادة بناء تفاعل عامل الإرساء) ويضيف مجموعة من أوامر التكوين لهذا الغرض. تحقق من ذلك هنا: https://github.com/dansteen/controlled-compose

لاحظ أن الشفرة قد اكتملت ، لكنني في انتظار حل مشكلتين أوليتين قبل أن يتم استخدام هذا بالفعل.

جوس يمكن أن تستخدم الرقائق مرنة إلى حد ما لتأخير بدء تشغيل الحاويات، لقد كتبت بلوق وظيفة شرح كيف أن هذا يمكن أن يتحقق مع تغيير طفيف على صورتك هنا:

لدى Kubernetes مفهوم حاويات init وأتساءل عما إذا كان التركيب / السرب سيستفيد من مفهوم مماثل.

+1

أعتقد أنه من الأفضل ترك الخدمة التي تعرضها على حاوية تقرر ما إذا كانت جاهزة أو قادرة على الكشف عن خدمتها أم لا.

على سبيل المثال ، قد يعتمد تطبيق PHP على اتصال MySQL. لذا في حاوية PHP ENTRYPOINT ، كتبت شيئًا كهذا.

#!/bin/bash
cat << EOF > /tmp/wait_for_mysql.php
<?php
\$connected = false;
while(!\$connected) {
    try{
        \$dbh = new pdo( 
            'mysql:host=mysql:3306;dbname=db_name', 'db_user', 'db_pass',
            array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
        );
        \$connected = true;
    }
    catch(PDOException \$ex){
        error_log("Could not connect to MySQL");
        error_log(\$ex->getMessage());
        error_log("Waiting for MySQL Connection.");
        sleep(5);
    }
}
EOF
php /tmp/wait_for_mysql.php
# Rest of entry point bootstrapping

بهذه الطريقة ، يمكنني إضافة أي منطق للتأكد من أنه قد تم حل تبعيات الخدمة التي أعرضها ، أي php.

نابين نيبال شريب:

أعتقد أنه من الأفضل ترك الخدمة التي تعرضها على حاوية تقرر ما إذا كانت جاهزة أو قادرة على الكشف عن خدمتها أم لا.

يمكنك بالطبع ترميز هذا السلوك في كل حاوية تستخدم ملف
حاوية MySql. ولكن إذا تغير شيء ما في خدمة MySql ، فأنت كذلك
تغيير جميع الحاويات التابعة ، ناهيك عن الترميز المتكرر
في كل حاجة. هذا ليس جافًا ، لا يوجد عقد مستقر وبالتالي سيكون كذلك
يؤدي إلى أنظمة هشة.

من وجهة نظر حرفة البرمجيات ، يجب أن يكون هناك نوع من
"جاهزية الحاوية SPI" ، والتي يمكن لمطور الحاوية تنفيذها. على
على الجانب الآخر ، يجب أن يكون هناك "واجهة برمجة تطبيقات جاهزية الحاويات" ، والتي يمكن أن يكون
يمكن أن تعتمد على الخدمات.

أولريش

realulim أوافق على ضرورة

ومع ذلك ، إذا كان التغيير يتعلق بمعلمات مثل DB_HOST و DB_NAME و DB_USER و DB_PASSWORD. يمكن تمرير هذه على أنها ARG (وسيطة) ومشاركتها من قبل جميع الحاويات ذات الصلة. إذا كنت تستخدم ملف docker-compose.yml ، فسيحدث التغيير في ملف واحد.

وأوافق تمامًا على أن وجود واجهة برمجة تطبيقات للتحقق من استعداد الحاوية هو الطريقة الحقيقية لحل هذا ، لكنني ما زلت أعتقد أن الخدمة التي يتم الكشف عنها ستكون أفضل مرشح للإعلان عن ذلك.

الحل until nc -z localhost 27017; do echo Waiting for MongoDB; sleep 1; done

@ piotr-s-brainhub يذكر من التعليقات أعلاه أن وجود منفذ مفتوح لا يعني أن الخدمة جاهزة.

هل يمكننا الحصول على حالة استعداد اختيارية يمكن تشغيلها إما عن طريق السجلات أو فتح المنفذ أو تأخير الوقت؟ شيء مثل:

ready_when:
  in_logs: `MySQL init process done`
  ports_open:
  - 3306

لقد أدركت للتو أن انتظار أن تصبح حاويات التبعية جاهزة يمكن تنفيذها بسهولة باستخدام أدوات مثل ansible. هل استخدم أي شخص هذا النهج؟ هل يمكنك بسهولة استبدال عامل البناء بـ ansible / chef / puppet؟ أي مشروع على جيثب يوضح هذا النهج؟

ملاحظة: أتفهم أهمية كتابة خدمة قوية يمكن تشغيلها حتى عندما لا تتوفر تبعياتها في الوقت الحالي. هذا ليس السؤال.

لقد قمت بحل هذا في الوقت الحاضر بأداة كتبتها: https://github.com/betalo-sweden/await

يمكنه الانتظار حتى تتوفر قائمة معينة من الموارد ، ومتابعة ما تريد متابعته ، إما بالانتقال إلى الأمر التالي ضمنيًا أو الاتصال به صراحة.

djui ، ما الذي ينتظره أثناء انتظار مورد معين؟

derekmahar استطلاعات الرأي. لديها مهلة افتراضية 60 ثانية. في كل مرة يتعذر عليه رؤية المورد ، سيعيد المحاولة في فترات زمنية من 1 ثانية. لا يقوم حاليًا بالكشف المتزامن عن الموارد ، لذا فهو متسلسل ، ولكن تبين أنه جيد بما يكفي ويمكن إصلاحه.

استخدمه في السيناريو التالي:

أقوم بتدوير بنية أساسية لإنشاء عامل ميناء ثم تشغيل برنامج تشغيل اختبار التكامل. تبدأ خدمة السائق فقط بعد توفر جميع مكونات البنية التحتية ، باستخدام نظام الانتظار ؛ انتظار حتى تستدعي في النهاية أمر تشغيل السائق.

إليك طريقة للقيام بذلك باستخدام توجيه Docker HEALTHCHECK الجديد باستخدام make:

https://gist.github.com/mixja/1ed1314525ba4a04807303dad229f2e1

[تحديث: جوهر محدث للتعامل مع ما إذا كانت الحاوية خرجت برمز خطأ ، حيث يبلغ Docker 1.12 بغباء إلى حد ما حالة Healthcheck على الحاوية الموقوفة على أنها "بدء"]

شكرا @ mixja ، حل جميل.

mixja ، حل جميل! هذه هي بالضبط الوظيفة التي أتوقع أن تظهر خارج الصندوق. لكن السؤال الآن هو إذا بدأت الحاويات الخاصة بك يدويًا ، فلماذا تحتاج إلى إنشاء عامل ميناء على الإطلاق؟

للاختبار ، أستخدم https://github.com/avast/docker-compose-gradle-plugin وهو يستخدم Docker healthcheck أيضًا - لا مزيد من التوقفات المصطنعة ، إنشاءات أسرع.

korya - لا تعد أداة Docker

mixja حسنا ، قد تكون أنت على حق. ولكن كما أشار العديد من الأشخاص في هذا الموضوع ، هناك حاجة ماسة إلى وظيفة التنسيق في بيئات الاختبار ، وعندما يكون هناك عامل ميناء مؤلف في صندوق الأدوات الخاص بك ، فمن المغري جدًا طلب هذا النوع من الوظائف من تكوين عامل الميناء.

في الواقع ، وفقًا للمستندات ، "يعد Compose أداة لتحديد تطبيقات Docker متعددة الحاويات وتشغيلها". على الرغم من أنه لا يذكر أن إنشاء أداة تنسيق ، أعتقد أنه من منظور المستخدم (على سبيل المثال أنا) من الطبيعي أن نتوقع من "أداة لتعريف وتشغيل تطبيقات Docker متعددة الحاويات" لدعم إدارة التبعية الأساسية بين الحاويات المُدارة خارج الصندوق.

أنا لا أقول أن الأداة يجب أن تدعمها. كل ما أقوله هو أنه من الطبيعي جدًا توقع ذلك. بخلاف ذلك ، يتعين على الجميع التوصل إلى طرق فائقة الذكاء للقيام بذلك. في الواقع ، نحن نستخدم برنامج bash النصي يفعل شيئًا مشابهًا لما يفعله makefile الخاص بك.

mixjakorya أود أن تحسين لغتي أداة انتظار وأود أن أسألك عن ردود الفعل ما إصدارات MAKEFILE تنص على أنه مفقود / أكثر ملاءمة / تمكين أكثر من await .

يبدو أن إصدار healthcheck + make يبدو وكأنه عرض "عالمي" ، ولا توجد حاوية واحدة تعرف الحالة العامة (لكن الملف makefile يعرف) و await هي طريقة عرض "محلية" ، كل حاوية ممكّنة تعرف (فقط) ما يحتاج إلى معرفته ، على غرار depends_on أو links . علاوة على ذلك ، تفضل شحن الحاوية بالأدوات المطلوبة للتحقق الصحي (والذي يكون أحيانًا هو الافتراضي ، على سبيل المثال mysqlshow ) وإلا اترك ملف Dockerfile دون تغيير. بالإضافة إلى ذلك ، يبدو أنك تستخدم عامل إنشاء السفن ليس للتكوين بشكل أساسي بعد الآن ولكن بشكل أساسي للتكوين المرن (على سبيل المثال ، يجب أن يكون docker-compose up -d mysql معادلاً لـ docker run -d -e ... -v ... -p ... mysql ).

مرحبًا djui - من المحتمل أن تكون وجهة نظر فلسفية ، لكنني أعتقد أن الفرضية الكاملة لـ HEALTHCHECK تعزز السلوك الصحيح - أي يمكن أن توفر الحاوية وسيلة لتأسيس صحة الحاوية ، دون أي تبعيات خارجية.

لا ينتقص هذا بأي حال من الأحوال من قيمة وجود شيء خارجي للتحقق من الاتصال ، ولكنني عادةً ما أقوم بإجراء مجموعة من اختبارات القبول لتغطية هذا لأنك تريد التحقق من الاتصال وغير ذلك الكثير (أي وظائف التطبيق). بالطبع لا يمكنك تشغيل هذا المستوى من الاختبار بشكل عام حتى يتم إنشاء بيئة كاملة ونطاق أداة await الخاصة بك والأساليب الأخرى التي استخدمتها في الماضي (Ansible playbooks مغلفة بـ agent container) حقًا على تنظيم إعداد البيئة بشكل صحيح (ليس الهدف النهائي لاختبار القبول) وحتى الآن كان النهج الوحيد المتاح في عالم Docker.

مع Docker 1.12 لدينا الآن وسيلة لاستبطان بيئة Docker والقدرة على استخدام التركيبات الراسخة (مثل آليات bash / shell) "لانتظار" حالة معينة ، بالطبع طالما أن حاوياتنا حددت فحوصات الصحة الخاصة بها . أرى قيمة أكبر في الاستفادة من الإمكانات الأصلية للمنصة وتشجيع مالكي الحاويات على تحديد فحوصاتهم الصحية ، بدلاً من الاعتماد على النهج الخارجي التاريخي (لقد بدأت عملية التقديم الخاصة بي ، ولم تعد مشكلتي). يلجأ إلى.

كقياس ذي صلة ، ضع في اعتبارك AWS CloudFormation ومفهوم مجموعات القياس التلقائي وتنظيم التحديثات الدورية. كيف يعرف CloudFormation ما إذا كان المثيل الجديد "سليمًا" جاهزًا للعمل ويمكننا قتل مثيل قديم وبدء تشغيل مثيل جديد آخر؟ هل نكتب فحصًا صحيًا خارجيًا أم نعتمد على المثيل نفسه للإشارة إلى الصحة؟ الإجابة هي الأخيرة ، فهذا يعني أن مالك المثيل يمكنه تعيين أي معايير نجاح مطلوبة لمثيله ، ثم يشير إلى نظام التنسيق الشامل (أي CloudFormation) بأن المثيل "سليم".

فيما يتعلق بتعليقاتك حول Docker Compose - إنها أداة يمكن أن توفر كلا الجانبين اللذين ذكرتهما. الجزء docker-compose.yml هو مواصفات البيئة التركيبية المطلوبة ، بينما توفر أوامر docker-compose القدرة على التفاعل مع البيئة بعدة طرق. في الوقت الحالي ، نحتاج إلى أدوات تنسيق خارجية لأن docker-compose أساسي لا يؤدي إدارة التبعية بين الخدمات بشكل جيد بما فيه الكفاية. نظرًا لأن docker-compose يحصل على ميزات مثل دعم الفحص الصحي الأصلي ، فإن الهدف من أمر واحد docker-compose up سيكون أكثر واقعية ، بافتراض أننا سنكون قادرين على تحديد على سبيل المثال يجب وضع علامة على خدمة صحية من قبل يتم اعتباره "مرتفعًا" ، مما يعني أن خدماتنا التابعة تنتظر بشكل فعال حتى تصبح التبعية صحية.

mixja شكرا على الشرح التفصيلي. أعتقد

أرى قيمة أكبر في الاستفادة من الإمكانات الأصلية للمنصة

هو جيد / النقطة الرئيسية. فقط في انتظار Docker Compose للاستفادة من الفحوصات الصحية محليًا إما في فقط أتساءل عما إذا كان ينبغي / سيذهب إلى أبعد من ذلك ويؤدي بشكل أساسي إلى إسقاط الحاويات المرتبطة إذا تم تعيين ، على سبيل المثال ، --abort-on-container-exit وفحص صحي أثناء وقت التشغيل يعين علامة healthcheck على _unhealthy_.

الحل المؤقت المحتمل لمن يبحثون عن وظيفة delay لتشغيل الاختبارات:

لدي ملفان docker-compose yml. أحدهما للاختبار والآخر للتطوير. الفرق هو فقط في وجود حاوية sut في docker-compose.test.yml . يتم تشغيل حاوية sut pytest . كان هدفي هو اختبار المدى docker-compose وإذا pytest القيادة في sut فشل حاوية، لا تعمل تنمية docker-compose . هذا ما توصلت إليه:

# launch test docker-compose; note: I'm starting it with -p argument
docker-compose -f docker-compose.test.yml -p ci up --build -d
# simply get ID of sut container
tests_container_id=$(docker-compose -f docker-compose.test.yml -p ci ps -q sut)
# wait for sut container to finish (pytest will return 0 if all tests passed)
docker wait $tests_container_id
# get exit code of sut container
tests_status=$(docker-compose -f docker-compose.test.yml -p ci ps -q sut | xargs docker inspect -f '{{ .State.ExitCode  }}' | grep -v 0 | wc -l | tr -d ' ')
# print logs if tests didn't pass and return exit code
if [ $tests_status = "1" ] ; then
    docker-compose -f docker-compose.test.yml -p ci logs sut
    return 1
else
    return 0
fi

الآن يمكنك استخدام الكود أعلاه في أي وظيفة من اختيارك (اسمي test ) وقم بشيء من هذا القبيل:

test
test_result=$?
if [[ $test_result -eq 0 ]] ; then
    docker-compose -f docker-compose.yml up --build -d
fi

يعمل جيدًا بالنسبة لي ولكن ما زلت أتطلع إلى رؤية docker-compose يدعم هذا النوع من الأشياء في الأصل :)

+1

ربما يمكن دعم الأشياء التي تعتبر خارج جوهر عامل عامل البناء من خلال السماح بالمكونات الإضافية؟ على غرار الطلب رقم 1341 ، يبدو أن هناك وظائف إضافية قد يجدها البعض مفيدة ولكنها لا تتماشى بالضرورة مع الرؤية الحالية. ربما يوفر دعم نظام مكون إضافي مثل المقترح بواسطة # 3905 طريقة للسماح بالتركيز على مجموعة أساسية من القدرات وإذا لم تكن هذه واحدة ، فيمكن لأولئك الذين يريدون ذلك لحالة الاستخدام الخاصة بهم كتابة مكون إضافي للتعامل مع أداء up مختلف؟

سيكون من الجيد أن تكون قادرًا على جعل docker-compose بمثابة نقطة دخول لجميع المشاريع التي لدينا محليًا حول إعداد بيئة عامل الإرساء ، بدلاً من الحاجة إلى إضافة برنامج نصي أمام الجميع ليكون بمثابة نقطة إدخال افتراضية بدلاً من الأشخاص الذين يحتاجون إلى تذكر تشغيل البرنامج النصي للحالات الفردية.

إليك طريقة للقيام بذلك باستخدام healthcheck وإنشاء عامل الإرساء 2.1+ :

version: "2.1"
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
    healthcheck:
      test: mysqladmin -uroot -ppassword ping
      interval: 2s
      timeout: 5s
      retries: 30
  web:
    image: nginx:latest # your image
    depends_on:
      db:
        condition: service_healthy

هنا يبدأ docker-compose up حاوية الويب فقط بعد اعتبار حاوية db سليمة.

آسف إذا تم ذكره بالفعل ، لكن لا أعتقد أنه تم نشر حل كامل.

هذه طريقة لـ PostgreSQL.

شكرا @ سيلكس 👍

version: '2.1'
services:
  db:
    image: postgres:9.6.1
    healthcheck:
      test: "pg_isready -h localhost -p 5432 -q -U postgres"
      interval: 3s
      timeout: 5s
      retries: 5

Silex للأسف مع الإصدار "3" وهذا التنسيق:

    image: nginx:latest # your image
    depends_on:
      db:
        condition: service_healthy

أحصل على ERROR: The Compose file './docker-compose.yml' is invalid because: depends_on contains an invalid type, it should be an array

2.1 يستمر في دعمه ولن يتم إهماله. 3.x مخصص بشكل أساسي لوضع خدمات السرب (غير محلي).

  From: Vlad Filippov <[email protected]>

إلى: docker /
نسخة إلى: mbdas [email protected] ؛ أذكر [email protected]
تاريخ الإرسال: الأربعاء 8 مارس 2017 الساعة 11:45 صباحًا
الموضوع: Re: [عامل إرساء / إنشاء] هل هناك طريقة لتأخير بدء تشغيل الحاوية لدعم الخدمات التابعة مع وقت بدء تشغيل أطول (# 374)

Silex للأسف مع الإصدار "3" وهذا التنسيق: image: nginx: أحدث # صورتك
يعتمد على:
ديسيبل:
الحالة: خدمة_صحية
تلقيت خطأ: ملف الإنشاء "./docker-compose.yml" غير صالح لأن: services.auth.depends_on يحتوي على نوع غير صالح ، يجب أن يكون مصفوفة—
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو اعرضها على GitHub ، أو قم بكتم صوت الموضوع.

2.1 يستمر في دعمه ولن يتم إهماله. 3.x مخصص بشكل أساسي لوضع خدمات السرب (غير محلي).

شكر!

vladikoff : مزيد من المعلومات حول الإصدار 3 على https://github.com/docker/compose/issues/4305

في الأساس ، لن يتم دعمه ، عليك أن تجعل حاوياتك تتحمل الأخطاء بدلاً من الاعتماد على عامل الميناء.

أعتقد أنه يمكن إغلاق هذا الآن.

للأسف ، لم تعد الحالة

website:
    depends_on:
      - 'postgres'
    build: .
    ports:
      - '3000'
    volumes:
      - '.:/news_app'
      - 'bundle_data:/bundle'
    entrypoint: ./wait-for-postgres.sh postgres 5432

  postgres:
    image: 'postgres:9.6.2'
    ports:
      - '5432'

wait-for-postgres.sh:

#!/bin/sh

postgres_host=$1
postgres_port=$2
shift 2
cmd="$@"

# wait for the postgres docker to be running
while ! pg_isready -h $postgres_host -p $postgres_port -q -U postgres; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

>&2 echo "Postgres is up - executing command"

# run the command
exec $cmd

تعد نقطة الإدخال المخصصة @ slava-nikulin ممارسة شائعة ، فهي الطريقة الوحيدة (عامل عامل الميناء الأصلي) التي يمكنك من خلالها تحديد جميع الشروط التي تحتاجها والتحقق منها قبل بدء تشغيل تطبيقك في حاوية.

الحقيقة هي أنه كان هناك الكثير من الجدل وأعتقد أن الدعم 2.x للدعم المشروط للتكامل مع الفحوصات الصحية وطلب بدء التشغيل كان دعمًا تمس الحاجة إليه. لا يدعم Docker الكبسولات المحلية للحاويات محليًا وعندما يفعل ذلك ، سيتعين عليه دعم شيء مشابه مرة أخرى تمامًا مثل kubernetes على سبيل المثال الذي يوفر الدلالات.

Docker 3.x عبارة عن سلسلة لجلب دعم السرب إلى التركيب ، وبالتالي تم إسقاط مجموعة من الخيارات مع مراعاة الطبيعة الموزعة.

تحافظ السلسلة 2.x على ميزات التكوين الأصلية / الهيكل المحلي.

يجب أن يكتشف Docker كيفية دمج هذين الإصدارين لأن إجبار السرب على الإنشاء عن طريق تقليل مجموعة ميزات الإنشاء ليس اتجاهًا مرحبًا به.

في 10 مايو 2017 ، الساعة 8:15 مساءً ، كتب سلافا نيكولين إخطارات github.com:

للأسف ، لم تعد الحالة مدعومة في الإصدار 3. هذا هو الحل الذي وجدته:

موقع الكتروني:
يعتمد على:
- "بوستجرس"
بناء:.
الموانئ:
- "3000"
أحجام:
- ".: / news_app"
- "bundle_data: / bundle"
نقطة الدخول: ./wait-for-postgres.sh postgres 5432

postgres:
الصورة: ' postgres: 9.6.2 '
الموانئ:
- "5432"
wait-for-postgres.sh:

! / بن / ش

postgres_host = 1 دولار
postgres_port = 2 دولار
cmd = "$ @"

انتظر حتى يتم تشغيل عامل ميناء postgres

في حين ! pg_isready -h $ postgres_host -p $ postgres_port -q -U postgres؛ فعل

& 2 صدى "Postgres غير متوفر - نائم"
النوم 1
منجز

& 2 صدى "Postgres قيد التنفيذ - تنفيذ الأمر"

قم بتشغيل الأمر

exec $ cmd
-
أنت تتلقى هذا لأنه تم ذكرك.
قم بالرد على هذه الرسالة الإلكترونية مباشرةً ، أو اعرضها على GitHub ، أو قم بكتم صوت الموضوع.

كنت قادرا على فعل شيء كهذا
// start.sh

#!/bin/sh
set -eu

docker volume create --name=gql-sync
echo "Building docker containers"
docker-compose build
echo "Running tests inside docker container"
docker-compose up -d pubsub
docker-compose up -d mongo
docker-compose up -d botms
docker-compose up -d events
docker-compose up -d identity
docker-compose up -d importer
docker-compose run status
docker-compose run testing

exit $?

// status.sh

#!/bin/sh

set -eu pipefail

echo "Attempting to connect to bots"
until $(nc -zv botms 3000); do
    printf '.'
    sleep 5
done
echo "Attempting to connect to events"
until $(nc -zv events 3000); do
    printf '.'
    sleep 5
done
echo "Attempting to connect to identity"
until $(nc -zv identity 3000); do
    printf '.'
    sleep 5
done
echo "Attempting to connect to importer"
until $(nc -zv importer 8080); do
    printf '.'
    sleep 5
done
echo "Was able to connect to all"

exit 0

// في ملف إنشاء عامل الإرساء الخاص بي

  status:
    image: yikaus/alpine-bash
    volumes:
      - "./internals/scripts:/scripts"
    command: "sh /scripts/status.sh"
    depends_on:
      - "mongo"
      - "importer"
      - "events"
      - "identity"
      - "botms"

لدي مشكلة مماثلة ولكن مختلفة قليلا. يجب أن أنتظر MongoDB لبدء وتهيئة مجموعة النسخ المتماثلة.
أنا أقوم بكل الإجراءات في عامل ميناء. أي إنشاء مجموعة متماثلة المصادقة. لكن لدي برنامج نصي آخر من نوع python يجب أن أتصل فيه بالعقدة الأساسية لمجموعة النسخ المتماثلة. أتلقى خطأ هناك.

docker-compose.txt
Dockerfile.txt
وفي نص Python ، أحاول أن أفعل شيئًا كهذا
for x in range(1, 4): client = MongoClient(host='node' + str(x), port=27017, username='admin', password='password') if client.is_primary: print('the client.address is: ' + str(client.address)) print(dbName) print(collectionName) break

أواجه صعوبة في القيام بذلك ، أي شخص لديه أي فكرة؟

patrickml إذا لم أستخدم تكوين عامل
أحتاج إلى 'cqlsh' لتنفيذ build_all.cql الخاص بي. ومع ذلك ، فإن 'cqlsh' غير جاهز ... يجب أن تنتظر 60 ثانية حتى تكون جاهزة.

القط Dockerfile

من المتجر / datastax / dse- الخادم: 5.1.8

جذر USER

قم بتشغيل apt-get update
قم بتشغيل apt-get install -y vim

إضافة db-scripts-2.1.33.2-RFT-01.tar / docker / cms /
COPY entrypoint.sh /entrypoint.sh

WORKDIR /docker/cms/db-scripts-2.1.33.2/
قم بتشغيل cqlsh -f build_all.cql

المستخدم dse

=============

الخطوة 8/9: قم بتشغيل cqlsh -f build_all.cql
—-> يعمل في 08c8a854ebf4
خطأ في الاتصال: ('غير قادر على الاتصال بأي خوادم' ، {'127.0.0.1': خطأ (111 ، "حاولت الاتصال بـ [('127.0.0.1' ، 9042)]. الخطأ الأخير: تم رفض الاتصال")})
أعاد الأمر '/ bin / sh -c cqlsh -f build_all.cql' رمزًا غير صفري: 1

يتطلب = var-lib-libvirt.mount var-lib-libvirt-images-ram.mount

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات