وبلاگ نت‌آرامآموزش، تجربه و راهکارهای زیرساخت

دیتابیس Docker بالا آمده ولی برنامه وصل نمی‌شود؛ انتظار برای آماده‌شدن سرویس

تشخیص خطای اتصال ابتدای اجرای Compose، تنظیم healthcheck و service_healthy و بررسی اعتبار اتصال برنامه به دیتابیس.

انتشار:
توسط تیم فنی نت‌آرام
۸ دقیقه زمان مطالعه
۰ دیدگاه
محتوای تخصصی، ساده و کاربردی
هماهنگ با هویت حرفه‌ای نت‌آرام
بازگشت به لیست مقالات
تصویر شاخص مقاله دیتابیس Docker بالا آمده ولی برنامه وصل نمی‌شود؛ انتظار برای آماده‌شدن سرویس در وبلاگ نت‌آرام
محتوای آموزشی وبلاگ نت‌آرام
با docker compose up برنامه و دیتابیس را اجرا می‌کنید. هر دو کانتینر روشن‌اند، اما برنامه در شروع می‌گوید به دیتابیس وصل نمی‌شود. چند ثانیه بعد اگر برنامه را دوباره اجرا کنید، مشکل ناپدید می‌شود. یک علت رایج این است که کانتینر دیتابیس شروع شده، اما خود دیتابیس هنوز آماده پذیرش اتصال نیست.
شروع کانتینر مانند روشن شدن چراغ یک فروشگاه است؛ ممکن است فروشنده هنوز صندوق را آماده نکرده باشد. Compose می‌تواند پیش از شروع برنامه منتظر موفق شدن آزمون سلامت دیتابیس بماند. با این حال، اتصال نادرست، رمز اشتباه یا نبودن جدول‌ها هم علل جداگانه‌اند و با یک گزینه زمان‌بندی حل نمی‌شوند.
در این راهنما نمونه ما سرویسی به نام web و دیتابیسی به نام db در Docker Compose است. نام‌ها، نسخه دیتابیس و دستورات واقعی شما ممکن است متفاوت باشند. به دسترسی مجاز به Docker، فایل Compose و نسخه پشتیبان معتبر از داده‌ها نیاز دارید. تغییر و بازسازی سرویس تولیدی را در زمان مناسب انجام دهید.

۱. اول زمان خطا و وضعیت دو سرویس را مقایسه کنید

از پوشه پروژه و با همان گزینه‌های فایل Compose که برای استقرار استفاده می‌کنید:
کد / دستورdocker compose ps
ستون وضعیت نشان می‌دهد هر سرویس اجرا، متوقف یا در حال راه‌اندازی است. سپس گزارش اخیر هر دو را کنار هم بخوانید:
کد / دستورdocker compose logs --since 15m --tail 100 db web
اگر web پیش از پیام آماده شدن دیتابیس خطای اتصال داده و بعد از آماده شدن دیتابیس اجرای دوباره‌اش موفق است، ترتیب راه‌اندازی یک احتمال قوی است. اگر خطا در تمام زمان‌ها ادامه دارد، نام میزبان، پورت، رمز، شبکه یا خود دیتابیس را هم بررسی کنید. گزارش‌ها ممکن است اطلاعات خصوصی داشته باشند؛ آن‌ها را بدون حذف مقادیر حساس ارسال نکنید.
برای دیدن سرویس‌های تعریف‌شده:
کد / دستورdocker compose config --services
نام سرویس‌ها را دقیق از همین خروجی بردارید. اسم کانتینر تولیدشده توسط Compose الزاماً با نام سرویس یکی نیست.

۲. آیا دیتابیس واقعاً آماده پذیرش اتصال است؟

اگر سرویس شما PostgreSQL است و ابزار pg_isready در همان کانتینر وجود دارد، نام کاربر و دیتابیس نمونه را با مقادیر خودتان عوض کنید:
کد / دستورdocker compose exec db pg_isready -U app -d appdb
پیامی مانند accepting connections نشان می‌دهد PostgreSQL در آن نقطه آماده پذیرش اتصال است. پیام rejecting connections یا no response می‌تواند نشان دهد هنوز آماده نیست یا به آن نشانی دسترسی وجود ندارد. این تست الزاماً درست بودن رمز، دسترسی برنامه از شبکه دیگر یا کامل بودن جدول‌ها را ثابت نمی‌کند.
اگر برای دیتابیس healthcheck تعریف شده، شناسه کانتینر را بگیرید:
کد / دستورdocker compose ps -q db
شناسه را به جای CONTAINER_ID قرار دهید:
کد / دستورdocker inspect --format '{{json .State.Health}}' CONTAINER_ID
در خروجی، starting، healthy یا unhealthy و چند نتیجه اخیر آزمون دیده می‌شود. اگر خروجی null است، ممکن است healthcheck تعریف نشده باشد. اگر سرویس چند replica دارد، هر کانتینر را جداگانه بررسی کنید. در صورت unhealthy بودن، راهنمای تشخیص healthcheck Docker به خواندن خطای دقیق کمک می‌کند.

۳. نام میزبان و پورت را درست انتخاب کنید

در شبکه پیش‌فرض یک پروژه Compose، سرویس‌ها معمولاً با نام سرویس یکدیگر را پیدا می‌کنند. اگر برنامه در کانتینر جداگانه است، localhost داخل آن به همان کانتینر برنامه اشاره دارد، نه خودکار به دیتابیس. در مثال رایج، میزبان دیتابیس برای web می‌تواند db و پورت داخلی PostgreSQL مقدار ۵۴۳۲ باشد.
اگر در فایل Compose پورتی مانند 5433:5432 منتشر شده، ۵۴۳۳ پورت میزبان و ۵۴۳۲ پورت داخل کانتینر دیتابیس است. ارتباط سرویس‌ها در شبکه مشترک معمولاً از نام سرویس و پورت داخلی استفاده می‌کند. اگر شبکه سفارشی، alias یا چند پروژه دارید، نام و شبکه واقعی خود را بررسی کنید.
برای دیدن شبکه‌های سرویس برنامه، ابتدا شناسه کانتینر web را با docker compose ps -q web بگیرید، سپس:
کد / دستورdocker inspect --format '{{json .NetworkSettings.Networks}}' CONTAINER_ID
همین بررسی را برای db انجام دهید. وجود شبکه مشترک یک سرنخ لازم است، اما صحت رمز یا پاسخ SQL را ثابت نمی‌کند. خروجی شبکه ممکن است اطلاعات خصوصی داشته باشد.

۴. نمونه healthcheck برای PostgreSQL

اگر image شما واقعاً PostgreSQL است و متغیرهای POSTGRES_USER و POSTGRES_DB داخل سرویس تعریف شده‌اند، در فایل Compose می‌توانید به بخش موجود db تنظیمی مانند این اضافه کنید:
کد / دستورservices: db: healthcheck: test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] interval: 5s timeout: 3s retries: 10 start_period: 30s
این فقط بخش لازم برای توضیح است؛ تعریف image، volume و بقیه تنظیمات فعلی را حذف نکنید. $$ باعث می‌شود علامت دلار برای shell داخل کانتینر باقی بماند، به جای اینکه Compose از محیط میزبان مقدار را جایگزین کند. interval فاصله آزمون، timeout سقف هر آزمون، retries تعداد شکست‌های متوالی و start_period فرصت راه‌اندازی اولیه است.
آزمون‌ها ممکن است در زمان start_period هم اجرا شوند؛ شکست اولیه معمولاً در شمارش نهایی لحاظ نمی‌شود، اما پس از اولین موفقیت، شکست‌های بعدی شمرده می‌شوند. مقدارهای بالا مثال‌اند؛ با زمان واقعی راه‌اندازی و نسخه Docker خود تنظیمشان کنید.
برای MySQL، Redis یا سرویس دیگر، دستور سلامت مخصوص همان محصول را از مستند image انتخاب کنید. pg_isready دستور PostgreSQL است و برای همه دیتابیس‌ها کار نمی‌کند.

۵. برنامه را به سلامت دیتابیس وابسته کنید

در همان فایل Compose، زیر سرویس web:
کد / دستورservices: web: depends_on: db: condition: service_healthy
این تنظیم به Compose می‌گوید هنگام ساخت و شروع web صبر کند تا healthcheck سرویس db موفق شود. اگر دیتابیس هیچ healthcheck معتبری نداشته باشد، شرط سلامت قابل استفاده نیست. نسخه Compose را با دستور زیر ببینید و پشتیبانی قالب فایل و گزینه‌ها را با مستند همان نسخه تطبیق دهید:
کد / دستورdocker compose version
اگر جدول‌ها یا migrationها نیز باید آماده باشند، پذیرش اتصال توسط دیتابیس کافی نیست. migration را با روش مستند برنامه اجرا کنید و نتیجه موفق آن را پیش‌شرط شروع بخش وابسته قرار دهید. در نسخه‌های پشتیبانی‌شده، یک سرویس کارِ یک‌باره می‌تواند با شرط service_completed_successfully مدل شود؛ فرمان و ترتیب واقعی به برنامه شما بستگی دارد.

۶. اعمال تغییر بدون از دست دادن داده

از فایل Compose نسخه پشتیبان داشته باشید و مشخص کنید داده دیتابیس در کدام volume یا مسیر نگهداری می‌شود. اعتبار تنظیم را از همان پوشه و با همان گزینه‌های استقرار بررسی کنید:
کد / دستورdocker compose config --quiet
خروجی خالی معمولاً یعنی اعتبارسنجی پیکربندی خطای گزارش‌شده‌ای نداشته است؛ موفقیت واقعی دیتابیس را ثابت نمی‌کند. docker compose config بدون --quiet ممکن است مقدارهای محرمانه را چاپ کند.
در بازه نگهداری و پس از بررسی اثر تغییر، سرویس‌های مربوط را اعمال کنید:
کد / دستورdocker compose up -d db web
Compose ممکن است کانتینرهای تغییرکرده را بازسازی کند و سرویس برای مدتی قطع شود. نام سرویس‌های واقعی را جایگزین کنید. از docker compose down -v برای حل مشکل اتصال استفاده نکنید؛ این گزینه می‌تواند volumeها و داده‌های آن‌ها را حذف کند.
حالا وضعیت را دوباره ببینید:
کد / دستورdocker compose ps
و گزارش تازه برنامه را بخوانید:
کد / دستورdocker compose logs --since 5m --tail 100 db web
دیتابیس باید آزمون سلامت را بگذراند و برنامه پس از آن بدون خطای اتصال اولیه شروع شود. اگر دیتابیس unhealthy باقی ماند، منتظر شدن نامحدود مشکل را حل نمی‌کند؛ خروجی healthcheck و لاگ دیتابیس را بررسی کنید.

۷. اتصال واقعی و خطاهای بعد از شروع را هم آزمایش کنید

اگر ابزار psql داخل کانتینر برنامه نصب است و PostgreSQL برای کاربر شما رمز می‌خواهد، یک آزمون مجاز می‌تواند چنین باشد:
کد / دستورdocker compose exec web psql -h db -p 5432 -U app -d appdb -W -c 'SELECT 1;'
رمز را فقط در اعلان تعاملی وارد کنید، نه داخل دستور. نام سرویس، میزبان، حساب و دیتابیس را با مقدار واقعی جایگزین کنید. بازگشت عدد 1 نشان می‌دهد همان مسیر، حساب و پرس‌وجوی ساده در آن لحظه کار کرده‌اند. اگر psql داخل image موجود نیست، از ابزار تشخیصی مجاز برنامه یا یک محیط آزمایشی با شبکه و تنظیمات همسان استفاده کنید.
اگر pg_isready موفق است ولی این اتصال شکست می‌خورد، پیام می‌تواند به رمز، مجوز حساب، نام دیتابیس یا مسیر شبکه برنامه اشاره کند. اگر اتصال SQL موفق است اما برنامه هنوز خطا می‌دهد، وجود جدول‌ها، migration و تنظیمات اختصاصی برنامه را بررسی کنید.
شرط service_healthy فقط آغاز هماهنگ را ساده می‌کند. پس از شروع نیز دیتابیس ممکن است قطع شود؛ برنامه باید خطای اتصال را مدیریت کند و طبق طراحی خود با فاصله و سقف مناسب دوباره تلاش کند. اگر رمز اشتباه است، تلاش بی‌پایان آن را درست نمی‌کند.
این روش در Docker روی سرور مجازی ایران و سرور اختصاصی ایران قابل استفاده است. تفاوت ترتیب شروع و شرط سلامت را در مستند رسمی Docker Compose ببینید.
اشتراک‌گذاری:
لینکدینتلگرامایکس

دیدگاه‌ها (۰)

دیدگاه‌های تاییدشده و پاسخ‌های تیم نت‌آرام