8.6 KiB
تشخیص «ریاستارت» سرور روی Coolify + رفع نویز لاگ + بررسی خطای ACME
پروژه
clinicpro (فقط فایلهای deploy — بدون تغییر در کد PHP/React)
زمینه
کاربر در لاگهای production (Coolify روی Ubuntu) میبیند که workerها مدام exit/spawn میشوند و نگران است سرور down میشود. تحلیل لاگ ارائهشده:
2026-07-08 07:40:54,435 INFO exited: worker-scheduler (exit status 0; expected)
2026-07-08 07:40:54,457 INFO spawned: 'worker-scheduler' with pid 1464
2026-07-08 07:40:54,460 INFO exited: worker-async (exit status 0; expected)
2026-07-08 07:40:54,468 INFO spawned: 'worker-async' with pid 1465
2026-07-08 07:40:55,674 INFO success: worker-async entered RUNNING state ...
این crash نیست. این رفتار طراحیشده است:
docker/supervisord.confهر دو worker را با--time-limit=3600اجرا میکند → هر worker دقیقاً هر ۱ ساعت با exit code 0 خارج میشود (به همین دلیل supervisor مینویسدexpected).- supervisord با
autorestart=trueدر کمتر از ۱ ثانیه دوباره spawn میکند. - در تمام مدت لاگ،
GET /healthهر ۱۵ ثانیه200برگردانده — یعنی nginx + php-fpm (وبسرور اصلی) هرگز down نبوده. - recycle ساعتیِ consumer الگوی استاندارد Symfony Messenger است (جلوگیری از نشت حافظه و connection کهنه به DB/Redis). مستندات Coolify هم healthcheck/restart policy را همینطور توصیه میکند.
اما یک مشکل واقعی در لاگ هست که میتواند در آینده باعث «down شدن» واقعی (خطای TLS) شود:
GET /.well-known/acme-challenge/hb1abFQX9d-... HTTP/1.1" 404
"Mozilla/5.0 (compatible; Let's Encrypt validation server; ...)"
سرور validation لتسانکریپت برای دامنه clinic-pro.ir چالش HTTP-01 فرستاده و به جای اینکه Traefik (پراکسی Coolify) خودش جواب بدهد، درخواست به کانتینر app رسیده و 404 گرفته. اگر این وضع ادامه پیدا کند تمدید گواهی شکست میخورد و بعد از انقضای cert فعلی، سایت با خطای TLS از دسترس خارج میشود — کاربر آن را «سرور down شد» میبیند.
فایلهای مرتبط
| فایل | نقش |
|---|---|
docker/supervisord.conf |
supervisor داخل کانتینر: nginx + php-fpm + دو worker با --time-limit=3600 -v |
docker-compose.yml |
حالت Compose در Coolify: app + دو worker بهصورت سرویس جدا، همان --time-limit=3600 -v |
supervisor.conf |
نسخه Liara — همان الگو |
docker/healthcheck.sh |
healthcheck کانتینر: GET /health → exit 0/1 |
Dockerfile |
HEALTHCHECK --interval=15s --retries=5 --start-period=60s |
docs/ |
مقصد runbook جدید |
وضعیت فعلی
docker/supervisord.conf:
[program:worker-async]
command=php bin/console messenger:consume async --time-limit=3600 --memory-limit=128M -v
autorestart=true
[program:worker-scheduler]
command=php bin/console messenger:consume scheduler_default --time-limit=3600 -v
autorestart=true
فلگ -v باعث میشود هر بار restart شدن worker، بنر چندخطی «[OK] Consuming messages…» و «The worker will automatically exit…» در stdout چاپ شود — همین بنرها لاگ را شلوغ و «ریاستارت» را ترسناکتر از واقعیت نشان میدهند.
وظایف
۱. کاهش نویز لاگ workerها (بدون تغییر رفتار)
فلگ -v را از هر چهار محل حذف کن (دو program در docker/supervisord.conf، دو service در docker-compose.yml، دو program در supervisor.conf). --time-limit=3600 و --memory-limit=128M را دست نزن — recycle ساعتی عمداً وجود دارد و باید بماند.
command=php bin/console messenger:consume async --time-limit=3600 --memory-limit=128M
خطاهای واقعی worker همچنان از طریق monolog (stderr) دیده میشوند؛ -v فقط verbosity کنسول بود.
۲. Runbook تشخیص «restart واقعی» از «recycle عادی»
فایل docs/ops-restarts.md بساز (فارسی) با این محتوا:
- توضیح اینکه
exited (exit status 0; expected)+ spawn فوری = recycle عادی و بیضرر است؛ نشانههای مشکل واقعی:exit statusغیرصفر،entered FATAL state،too many start retries، یا گپ در لاگهای/health. - دستورهای تشخیص روی سرور:
# آیا خودِ کانتینر ریاستارت شده؟ (uptime کانتینر vs uptime پروسه)
docker ps --format 'table {{.Names}}\t{{.Status}}' # Status باید Up X hours (healthy) باشد
docker inspect --format '{{.RestartCount}} {{.State.StartedAt}}' <container>
docker events --since 24h --filter event=restart --filter event=die
- اگر
RestartCountصفر است وStartedAtقدیمی → هیچ ریاستارت واقعیای در کار نیست؛ فقط recycle داخلی worker است. - بخش Coolify: فعالکردن Notifications (Telegram/Email) در Coolify برای event های container stop/unhealthy، تا down شدن واقعی بلافاصله اطلاع داده شود. ارجاع به مستندات:
https://coolify.io/docs/knowledge-base/notificationsوhttps://coolify.io/docs/knowledge-base/health-checks.
۳. بررسی و مستندسازی خطای ACME (مهمترین ریسک down شدن واقعی)
در همان docs/ops-restarts.md بخش «تمدید گواهی TLS» اضافه کن:
- علامت مشکل:
GET /.well-known/acme-challenge/... → 404در access log کانتینر app. چالش HTTP-01 باید توسط Traefik خود Coolify جواب داده شود و اصلاً نباید به app برسد؛ رسیدنش یعنی صدور/تمدید cert برای آن دامنه دارد شکست میخورد. - چکلیست رفع روی سرور Coolify:
- در Coolify → resource مربوط به app → تب Domains: مطمئن شو دامنه
clinic-pro.ir(وwwwاگر لازم است) دقیقاً با schemahttps://روی سرویسappثبت شده باشد. دامنهای که در Coolify ثبت نشده ولی DNS آن به سرور اشاره میکند، همین الگوی 404 را میسازد. - وضعیت فعلی cert را چک کن:
echo | openssl s_client -connect clinic-pro.ir:443 -servername clinic-pro.ir 2>/dev/null | openssl x509 -noout -dates - لاگ Traefik/proxy در Coolify (Servers → Proxy → Logs) را برای خطای acme بررسی کن.
- ارجاع:
https://coolify.io/docs/knowledge-base/proxy/traefik/overviewو بخش Domains در مستندات Coolify.
- در Coolify → resource مربوط به app → تب Domains: مطمئن شو دامنه
۴. سازگاری healthcheck
فقط بررسی (بدون تغییر مگر مغایرت پیدا شد): Dockerfile مقادیر interval=15s, retries=5, start-period=60s دارد و docker-compose.yml سرویس app همان مقادیر را — مطمئن شو یکسان بمانند. healthcheck های worker در compose (ps | grep messenger:consume) در لحظه exit ساعتیِ worker ممکن است یک بار fail شوند؛ چون retries: 3 و interval: 30s است، سه شکست پیاپی لازم است و restart کانتینر (که Coolify آن را event میکند) رخ نمیدهد مگر worker واقعاً بالا نیاید — این را در runbook هم ذکر کن.
نکات مهم
- هیچ تغییری در رفتار runtime نده جز حذف
-v.--time-limitوautorestartعمدی و صحیحاند. - این پرامپت فایل PHP/React را لمس نمیکند → migration و بهروزرسانی
docs/api/لازم ندارد. docs/ops-restarts.mdفارسی نوشته شود (زبان محصول)، ولی دستورها و خروجیهای shell انگلیسی بمانند.- سه فایل config (
docker/supervisord.conf،docker-compose.yml،supervisor.conf) باید بعد از تغییر همچنان آینه هم بمانند — کامنتهای بالای هر فایل همین را میگویند. - بعد از merge، اعمال روی سرور نیاز به redeploy در Coolify دارد؛ در runbook یادآوری کن.