[{"data":1,"prerenderedAt":172},["ShallowReactive",2],{"seo-verification":3,"blog-depends-on-لا-يكفي-healthcheck-لـ-postgresql-في-compose-ar":6},{"google":4,"bing":5},"EycwPY2XMyTkVzas3n1ygeNJFGAH513qrMjfDljzsMQ","",{"id":7,"slug":8,"slugs":9,"title":12,"excerpt":13,"readTime":14,"views":15,"isPinned":16,"publishedAt":17,"category":18,"categories":23,"featuredImage":25,"bgImage":26,"posterImage":27,"relatedSolution":25,"intro":28,"sections":29,"ctaTitle":117,"ctaBody":118,"ctaButton":119,"ctaUrl":120,"relatedPosts":121},282,"depends-on-لا-يكفي-healthcheck-لـ-postgresql-في-compose",{"fr":10,"en":11,"ar":8},"docker-compose-depends-on-healthcheck","depends-on-is-not-enough-postgresql-healthcheck-in-compose","depends_on لا يكفي: healthcheck لـ PostgreSQL في Compose","لماذا لا يضمن `depends_on` وحده جاهزية PostgreSQL، وكيف تُعدّ healthcheck موثوقاً باستخدام `service_healthy` لتجنب race conditions عند الإقلاع.",9,0,false,"2026-08-19T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},3,"النشر","deploiement","bg-success\u002F10 text-success",[24],{"id":19,"name":20,"slug":21,"color":22,"icon":21},null,"\u002Fblog\u002Fcovers\u002Fbg.svg","\u002Fblog\u002Fcovers\u002Fdocker-compose-depends-on-healthcheck-poster.svg","تنطلق حاوياتك Docker، وتنتقل قاعدة البيانات إلى حالة `running` — ثم تتعطل تطبيقاتك فوراً برسالة `connection refused` أو `FATAL: role does not exist`. السبب في الغالب واحد: الشكل الافتراضي لـ `depends_on` ينتظر انطلاق الحاوية فقط، لا جاهزية الخدمة فعلياً. يوضح هذا الدليل كيفية إعداد healthcheck موثوق لـ PostgreSQL في ملف `docker-compose.yml` للتخلص من race condition مرة واحدة وإلى الأبد.",[30,34,44,47,75,107,111,114],{"type":31,"title":32,"body":33},"h2","لماذا يفشل `depends_on` الافتراضي","يستخدم `depends_on` افتراضياً شرط `service_started`، مما يعني أن Docker ينتظر فقط **انطلاق** الحاوية المستهدفة — أي أن عمليتها الرئيسية قد بدأت. هذا لا يقول شيئاً عن الحالة الداخلية للخدمة.\n\nيمرّ PostgreSQL، كمعظم قواعد البيانات، بعدة مراحل عند التهيئة: تُنفّذ الصورة الرسمية سكريبتات الإقلاع، وتنشئ الأدوار، وتُهيّئ الإضافات، وتُعدّ الـ cluster قبل أن تبدأ في قبول الاتصالات. يمكن أن تستغرق هذه العملية من ثوانٍ إلى أكثر من ثلاثين ثانية على VPS بقرص دافئ أو حجم غير محضَّر أو إضافات كثيرة.\n\nخلال هذا الوقت، يحاول تطبيقك — الذي يحترم توجيه `depends_on` — الاتصال بقاعدة البيانات، فيتلقى رفضاً صريحاً.",{"type":35,"title":36,"items":37},"ul","العواقب العملية لـ race condition عند الإقلاع",[38,39,40,41,42,43],"**`connection refused`** — مقبس TCP الخاص بـ PostgreSQL لم يُفتح بعد، ويفشل التطبيق عند أول استدعاء PDO أو SQLAlchemy.","**`FATAL: role does not exist`** — PostgreSQL يستمع، لكن سكريبتات التهيئة (`docker-entrypoint-initdb.d`) لم تُنشئ بعد الدور أو قاعدة البيانات.","**`FATAL: the database system is starting up`** — الـ cluster في طور الاسترداد بعد إيقاف نظيف؛ الاتصالات مرفوضة مؤقتاً.","**حلقة تعطل صامتة** — يعيد Docker تشغيل التطبيق باستمرار بفضل `restart: unless-stopped`، وتتكرر السجلات، ويبدو الأمر كخطأ في التطبيق.","**نتائج كاذبة في CI** — تفشل اختبارات التكامل بصورة متقطعة بحسب سرعة الـ runner.","**تبعيات متسلسلة** — إذا كانت واجهة برمجية تعتمد على تطبيق يعتمد على قاعدة بيانات، توارثت المشكلة ذاتها إن لم تكن سلسلة `depends_on` صحيحة في كل حلقة.",{"type":31,"title":45,"body":46},"المتطلبات الأساسية: Docker Compose v2 والإضافة الرسمية","شرط `service_healthy` **غير متاح** في Docker Compose v1 (ثنائي Python المُهمَل `docker-compose`). مدعوم منذ **Docker Compose v2**، الموزَّع كإضافة Go تحت أمر `docker compose` (بدون شرطة).\n\nللتحقق من إصدارك:\n\n```bash\ndocker compose version\n```\n\nيجب أن تُظهر المخرجات `Docker Compose version v2.x.x` أو أعلى. على Debian 12 وUbuntu 22.04+، الإضافة متاحة من مستودعات Docker الرسمية. إن كان لديك `docker-compose` (v1) بعد، انتقل: المشروع مُؤرشَف ولا يتلقى إصلاحات أمنية.\n\nلا تحتاج إلى أي تبعية إضافية لـ PostgreSQL: ‏`pg_isready` أداة أصيلة في الصورة الرسمية `postgres`، موجودة في جميع الـ tags منذ سنوات.",{"type":48,"title":49,"steps":50},"steps","إعداد healthcheck موثوق لـ PostgreSQL خطوة بخطوة",[51,54,57,60,63,66,69,72],{"title":52,"body":53},"فهم الفرق بين service_started و service_healthy","يقبل `depends_on` ثلاثة شروط:\n\n- `service_started` (افتراضي) — ينتظر انطلاق الحاوية فقط.\n- `service_healthy` — ينتظر حتى يُعيد healthcheck الحاوية `healthy`.\n- `service_completed_successfully` — للحاويات قصيرة العمر (jobs، migrations).\n\nلأي قاعدة بيانات، `service_healthy` هو الشرط الوحيد الذي يضمن أن الخدمة تقبل الاتصالات فعلاً.",{"title":55,"body":56},"كتابة healthcheck الخاص بـ PostgreSQL في خدمة `db`","أضف كتلة `healthcheck` مباشرة في تعريف خدمة `db`:\n\n```yaml\nservices:\n  db:\n    image: postgres:16\n    environment:\n      POSTGRES_USER: app\n      POSTGRES_PASSWORD: secret\n      POSTGRES_DB: appdb\n    healthcheck:\n      test: [\"CMD\", \"pg_isready\", \"-U\", \"app\", \"-d\", \"appdb\"]\n      interval: 5s\n      timeout: 5s\n      retries: 5\n      start_period: 30s\n```\n\nيستقبل الحقل `test` قائمة: العنصر الأول `CMD` (يُنفّذ Docker الأمر مباشرة)، تليه الوسائط. يُعيد `pg_isready` القيمة `0` إذا كان PostgreSQL جاهزاً لقبول الاتصالات بالمستخدم وقاعدة البيانات المحددَين، وكوداً غير صفري إذا لم يكن كذلك — وهو ما يُفسّره Docker على أنه `healthy` أو `unhealthy`.",{"title":58,"body":59},"فهم دور `start_period`","`start_period` هو **فترة السماح** الممنوحة للحاوية للتهيئة قبل أن تبدأ إخفاقات healthcheck في الاحتساب ضمن `retries`. خلال هذه الفترة، ينفّذ Docker healthcheck، لكن الإخفاق لا يزيد العداد.\n\nبدون `start_period`، فإن PostgreSQL الذي يستغرق 15 ثانية للتهيئة سيُخفق في أول 5 فحوصات (`interval: 5s` × 5 محاولات = 25 ثانية) وينتهي `unhealthy` قبل أن يصبح تشغيلياً.\n\nالقيمة الموصى بها هي **30 ثانية** لـ PostgreSQL القياسي: كافية لاستيعاب التهيئات البطيئة (أول إقلاع بحجم فارغ، إضافات ثقيلة) دون تأخير غير ضروري عند الإقلاع في الظروف العادية. `interval` و`start_period` متمايزان: `interval` يُوقّت الفحوصات في التشغيل الطبيعي، و`start_period` يحمي مرحلة الإقلاع.",{"title":61,"body":62},"كتابة `depends_on` مع `condition: service_healthy`","في كل خدمة تعتمد على قاعدة البيانات، استبدل الشكل المختصر لـ `depends_on` بالشكل المفصّل مع الشرط:\n\n```yaml\nservices:\n  app:\n    image: myapp:latest\n    depends_on:\n      db:\n        condition: service_healthy\n    environment:\n      DATABASE_URL: postgresql:\u002F\u002Fapp:secret@db:5432\u002Fappdb\n```\n\nبهذا الإعداد، ينتظر Docker حتى يُعيد healthcheck خدمة `db` القيمة `healthy` قبل تشغيل `app`. إذا أصبح `db` بحالة `unhealthy` بعد `retries` إخفاق، لا تنطلق `app`.",{"title":64,"body":65},"الاختبار باستخدام `docker compose up`","أطلق الـ stack وراقب التسلسل:\n\n```bash\ndocker compose up\n```\n\nسترى في السجلات أسطراً من قبيل:\n\n```\ndb  | database system is ready to accept connections\napp | Waiting for db to be healthy...\napp | Starting application server\n```\n\nللتحقق من حالة healthcheck في أي وقت:\n\n```bash\ndocker inspect \u003Cdb_container_name> | grep -A 5 '\"Health\"'\n```\n\nتُظهر المخرجات `Status: healthy` أو `starting` أو `unhealthy`، وتسرد مخرجات آخر الفحوصات.",{"title":67,"body":68},"حالة Redis: healthcheck مُكيَّف","لا يمتلك Redis أداة `redis-isready`، لكن معادلها هو `redis-cli ping`:\n\n```yaml\n  redis:\n    image: redis:7-alpine\n    healthcheck:\n      test: [\"CMD\", \"redis-cli\", \"ping\"]\n      interval: 5s\n      timeout: 3s\n      retries: 5\n      start_period: 10s\n```\n\nيُعيد `redis-cli ping` القيمة `PONG` وكود الخروج `0` إذا كان Redis يقبل الاتصالات. بما أن Redis يبدأ أسرع من PostgreSQL، تكفي `start_period: 10s` في الغالب.",{"title":70,"body":71},"حالة MySQL \u002F MariaDB: استخدام `mysqladmin ping`","لـ MySQL أو MariaDB، استخدم `mysqladmin ping`:\n\n```yaml\n  mysql:\n    image: mariadb:11\n    environment:\n      MYSQL_ROOT_PASSWORD: secret\n      MYSQL_DATABASE: appdb\n    healthcheck:\n      test: [\"CMD\", \"mysqladmin\", \"ping\", \"-h\", \"localhost\", \"-u\", \"root\", \"-psecret\"]\n      interval: 5s\n      timeout: 5s\n      retries: 5\n      start_period: 30s\n```\n\nتنبيه: يُدمج كلمة المرور مباشرة مع `-p` بلا مسافة (`-psecret`)، وهو السلوك المتوقع لـ `mysqladmin`. يظهر هذا الأمر في مخرجات `docker inspect`، لذا فضّل استخدام Compose secret أو متغير بيئة إن كانت السرية مطلوبة.",{"title":73,"body":74},"استكشاف الأخطاء: أربعة أخطاء شائعة","**`pg_isready: command not found`** — لا تستخدم الصورة الرسمية `postgres` (أو صورة مشتقة تتضمنها). تحقق باستخدام: `docker compose exec db which pg_isready`.\n\n**healthcheck في حلقة، لا يصل أبداً إلى `healthy`** — لا يُعيد `test` القيمة `0`. اختبر يدوياً: `docker compose exec db pg_isready -U app -d appdb`. إذا فشل الأمر، تحقق من متغيرات `POSTGRES_USER` و`POSTGRES_DB`.\n\n**`start_period` قصير جداً** — عند أول إقلاع بحجم فارغ، قد يستغرق PostgreSQL أكثر من 30 ثانية. ارفع القيمة إلى `60s` أو راقب السجلات: `database system was shut down at … LOG:  database system is ready to accept connections` يُشير إلى التأخير الفعلي.\n\n**الحاوية في حالة `unhealthy` دائمة** — بعد `retries` إخفاق، يُصنّف Docker الحاوية `unhealthy` لكنه لا يُعيد تشغيلها (ذلك دور `restart`). راجع `docker inspect` لمعرفة مخرجات آخر الفحوصات وتحديد الأمر الفاشل.",{"type":76,"title":77,"headers":78,"rows":82},"comparison","السلوك الافتراضي مقابل السلوك مع healthcheck",[79,80,81],"الحالة","السلوك الافتراضي (`service_started`)","مع `service_healthy`",[83,87,91,95,99,103],[84,85,86],"أول إقلاع، حجم فارغ","يبدأ التطبيق قبل جاهزية قاعدة البيانات → حلقة تعطل","ينتظر التطبيق حتى تكتمل تهيئة PostgreSQL ويقبل الاتصالات",[88,89,90],"إعادة التشغيل بعد إيقاف نظيف","قد يبدأ التطبيق خلال مرحلة استرداد PostgreSQL","ينتظر التطبيق حتى اكتمال الاسترداد",[92,93,94],"قاعدة بيانات بطيئة (إضافات، تهيئة ثقيلة)","race condition تعتمد على سرعة المضيف","لا race condition: healthcheck يتحقق من الحالة الفعلية",[96,97,98],"تبعيات متسلسلة (app → worker → db)","كل مكوّن يُدير محاولات إعادة الاتصال بنفسه","سلسلة الشروط تضمن ترتيب الإقلاع",[100,101,102],"اختبارات التكامل في CI","نتائج متقطعة تعتمد على سرعة الـ runner","نتائج حتمية ومتسقة",[104,105,106],"Redis أو MySQL بدلاً من PostgreSQL","المشكلة ذاتها، `depends_on` الافتراضي لا يُميّز","الحل ذاته، أمر الفحص مُكيَّف لكل محرك",{"type":108,"title":109,"body":110},"tip","`pg_isready` أم `SELECT 1`: أيهما تختار؟","يظهر نوعان من healthcheck لـ PostgreSQL في الاستخدام الشائع:\n\n- `[\"CMD\", \"pg_isready\", \"-U\", \"postgres\"]`\n- `[\"CMD-SHELL\", \"psql -U postgres -c 'SELECT 1'\"]\"`\n\n`pg_isready` **أكثر موثوقية** لسبب بسيط: يختبر فقط قدرة الخادم على قبول اتصالات TCP، دون فتح جلسة SQL. يُعيد القيمة `0` حالما يكون الخادم مستمعاً ويقبل المصافحة، وهو بالضبط ما يحتاجه التطبيق لمحاولة اتصاله الخاص.\n\nأما `SELECT 1` عبر `psql`، فيفتح جلسة SQL حقيقية وينفّذ استعلاماً. هو اختبار أعمق، لكنه قد يفشل لأسباب لا علاقة لها بتوافر الخادم (استنفاد حصة الاتصالات، `pg_hba.conf` غير مُعدَّ بصواب). للـ healthcheck، الاختبار الأدنى والمباشر هو الأفضل.",{"type":108,"title":112,"body":113},"تكييف فحص الصحة لـ Redis وMySQL","بالنسبة لـ ‎Redis، استبدل ‎`pg_isready` بـ ‎`CMD redis-cli PING` — تُرجع ‎`PONG` فور قبول الخادم للاتصالات. بالنسبة لـ ‎MySQL أو ‎MariaDB، استخدم ‎`CMD mysqladmin ping -h localhost -u root --password=$$MYSQL_ROOT_PASSWORD` مع رفع ‎`start_period` إلى ‎60s، إذ يستغرق تهيئة ‎MySQL وقتاً أطول من ‎PostgreSQL. نمط ‎`condition: service_healthy` متطابق بغض النظر عن الخدمة المستهدفة.",{"type":31,"title":115,"body":116},"الخطوات التالية","يُعدّ healthcheck مع `service_healthy` أحد إعدادات المتانة الواجب تفعيلها في الإنتاج. تستحق عدة نقاط أخرى الاهتمام ذاته قبل أي نشر مستدام: سياسة إعادة التشغيل `restart: unless-stopped`، حدود الموارد `deploy.resources.limits`، وتدوير السجلات `logging.options`. يمكنك الاطلاع على القائمة الكاملة في دليل **Docker Compose في الإنتاج: قائمة التحقق من 10 نقاط**.\n\nإذا نما الـ stack — خدمات متعددة أو مضيفون متعددون — فإن reverse proxy كـ Caddy أو Traefik ضروري لإدارة توجيه HTTPS. يفصّل دليل **Caddy أو Traefik أو Nginx Proxy Manager** معايير الاختيار حسب ملفك.\n\nلأتمتة نشر بنيتك التحتية بالكامل (VPS، Docker، الإعداد) بطريقة قابلة للتكرار، يرشدك دليل **Ansible لأتمتة خوادم VPS** خطوة بخطوة.","استضف stack Docker الخاص بك على VPS مخصص","يمنحك VPS ServOrbit وصولاً بصلاحيات root وعنوان IPv4 مخصصاً والموارد اللازمة لتشغيل stacks Docker Compose في الإنتاج. انشر في دقائق.","نشر الـ stack على VPS","\u002Fvps-cloud",[122,136,153],{"id":123,"slug":124,"slugs":125,"title":128,"excerpt":129,"readTime":130,"views":15,"isPinned":16,"publishedAt":131,"category":132,"categories":133,"featuredImage":25,"bgImage":26,"posterImage":135,"relatedSolution":25},229,"docker-compose-في-الإنتاج-قائمة-التحقق-من-10-نقاط",{"fr":126,"en":127,"ar":124},"docker-compose-production-checklist","docker-compose-in-production-10-point-checklist","Docker Compose في الإنتاج: قائمة التحقق من 10 نقاط","‎10 إعدادات Docker Compose يجب التحقق منها قبل أي نشر إنتاجي: إعادة التشغيل والفحوص الصحية والحدود والأسرار والسجلات.",14,"2026-08-06T00:00:00+00:00",{"id":19,"name":20,"slug":21,"color":22,"icon":21},[134],{"id":19,"name":20,"slug":21,"color":22,"icon":21},"\u002Fblog\u002Fcovers\u002Fdocker-compose-production-checklist-poster.svg",{"id":137,"slug":138,"slugs":139,"title":142,"excerpt":143,"readTime":144,"views":15,"isPinned":16,"publishedAt":131,"category":145,"categories":150,"featuredImage":25,"bgImage":26,"posterImage":152,"relatedSolution":25},227,"caddy-أم-traefik-أم-nginx-proxy-manager-أيهما-تختار",{"fr":140,"en":141,"ar":138},"choisir-reverse-proxy-vps-caddy-traefik-nginx","caddy-traefik-or-nginx-proxy-manager-which-to-choose","‏Caddy أم Traefik أم Nginx Proxy Manager: أيهما تختار؟","دليل المقارنة بين ‏Caddy و‏Traefik و‏Nginx Proxy Manager لاختيار بروكسي عكسي لـ‏Docker على خادم VPS. معايير وجدول مقارنة وتوصيات حسب الملف الشخصي.",10,{"id":146,"name":147,"slug":148,"color":149,"icon":148},5,"مقارنات","comparatif","bg-info\u002F10 text-info",[151],{"id":146,"name":147,"slug":148,"color":149,"icon":148},"\u002Fblog\u002Fcovers\u002Fchoisir-reverse-proxy-vps-caddy-traefik-nginx-poster.svg",{"id":154,"slug":155,"slugs":156,"title":159,"excerpt":160,"readTime":161,"views":162,"isPinned":16,"publishedAt":163,"category":164,"categories":169,"featuredImage":25,"bgImage":26,"posterImage":171,"relatedSolution":25},236,"أتمتة-إدارة-خوادم-vps-باستخدام-ansible",{"fr":157,"en":158,"ar":155},"ansible-automatiser-serveurs-vps","automating-vps-server-management-with-ansible","أتمتة إدارة خوادم VPS باستخدام Ansible","تعرّف على كيفية أتمتة إدارة أسطول خوادم VPS باستخدام ‎Ansible‎: الجرد والـ playbooks والأدوار والـ Vault لبنية تحتية قابلة للتكرار.",11,1,"2026-08-08T00:00:00+00:00",{"id":165,"name":166,"slug":167,"color":168,"icon":167},2,"الأتمتة","automatisation","bg-brand-action\u002F10 text-brand-action",[170],{"id":165,"name":166,"slug":167,"color":168,"icon":167},"\u002Fblog\u002Fcovers\u002Fansible-automatiser-serveurs-vps-poster.svg",1787580959507]