هر خطی که برنامه روی stdout یا stderr مینویسد، بسته به logging driver روی host ذخیره یا ارسال میشود. اگر driver فایلمحور بدون rotation باشد یا برنامه در retry loop هزاران خط در دقیقه تولید کند، Disk میتواند بدون رشد داده کسبوکار پر شود. پاککردن فایل log فقط نشانه را موقتاً حذف میکند و حتی ممکن است مدیریت Docker را مختل کند.
پاسخ سریع: ابتدا container و logging driver پرمصرف را با inspect و اندازهگیری host مشخص کنید. نرخ log و پیام تکراری را پیدا و علت برنامهای را اصلاح کنید. برای container، local یا driver مناسب با سقف max-size/max-file تنظیم کنید؛ سپس container را طبق برنامه recreate و rotation، دسترسی به تاریخچه و هشدار Disk را آزمون کنید.
Docker log از کجا میآید؟
برنامه یا entrypoint روی stdout/stderr مینویسد و Docker logging driver آن را مدیریت میکند. مسیر و format به driver بستگی دارد؛ نباید فرض کنید همیشه یک فایل JSON در مسیر ثابت وجود دارد. log داخل فایل application در volume مسیر دیگری است و با تنظیم driver Docker rotate نمیشود. journal، sidecar یا agent جمعآوری نیز ممکن است نسخه دیگری ذخیره کند.
اول driver فعال را پیدا کنید
تنظیم daemon default و تنظیم هر container را جدا بررسی کنید. ممکن است default امروز تغییر کرده باشد اما container قدیمی هنوز driver قبلی را استفاده کند. مستندات Docker تصریح میکنند تغییر default logging configuration روی containerهای تازه اثر میگذارد؛ برای container موجود recreate لازم است. پیش از آن مطمئن شوید backend مرکزی و command docker logs رفتار موردانتظار دارند.
چرا json-file رشد میکند؟
اگر rotation برای آن تنظیم نشده باشد، خروجی مداوم میتواند فایل را بزرگ کند. خود برنامه ممکن است هر request موفق، payload حجیم، stack trace تکراری یا healthcheck پرتکرار را log کند. rotation بدون کاهش log storm فقط سرعت پرشدن سهم تعیینشده را کنترل میکند؛ علت CPU، هزینه ingest و گمشدن signal در noise باقی میماند.
Driver محلی چه مزیتی دارد؟
logging driver محلی Docker برای storage کارآمد و rotation داخلی طراحی شده و بهطور پیشفرض محدودیت فایل دارد. انتخاب آن باید با نیاز خواندن log، نسخه Engine و agent مانیتورینگ سازگار باشد. اگر ابزار بیرونی مستقیماً فایل JSON داخلی Docker را tail میکند، تغییر driver آن integration را میشکند؛ بهتر است از interface پشتیبانیشده یا driver/collector رسمی استفاده شود.
تنظیم در Compose
services:
app:
image: registry.example/app@sha256:...
logging:
driver: local
options:
max-size: "20m"
max-file: "5"
اعداد مثالاند، نه پیشنهاد همگانی. نرخ رخداد، نیاز incident و ارسال مرکزی retention را تعیین میکند. optionها معمولاً رشته نوشته میشوند و باید با driver انتخابی سازگار باشند. image نمونه باید با digest واقعی جایگزین شود. خروجی نهایی Compose را بازبینی و ابتدا در staging اجرا کنید.
اگر json-file لازم است
برای compatibility میتوانید همان driver را با rotation معتبر تنظیم کنید. نام optionها را از مستندات نسخه Engine بررسی کنید. تغییر daemon.json نیازمند syntax صحیح و برنامه restart daemon است و ممکن است روی سرویسها اثر بگذارد؛ برای یک سرویس میتوان ابتدا config سطح container را آزمود. containerهای قبلی خودکار policy جدید نمیگیرند.
Log Storm را چگونه پیدا کنیم؟
- نرخ رشد Disk و زمان آغاز را مشخص کنید.
- containerهای همان بازه و restart count را ببینید.
- نمونه محدود log را با
--sinceیا--tailبخوانید. - پیام پرتکرار، level و request/job مشترک را دستهبندی کنید.
- dependency، retry و healthcheck را با همان زمان تطبیق دهید.
- قبل و بعد از اصلاح، نرخ خطوط/بایت را مقایسه کنید.
کل log چندگیگابایتی را در terminal یا تیکت بارگذاری نکنید. نمونه زمانی و شمارش پیام بهتر است و خطر افشای secret یا داده شخصی را کم میکند.
Retry Loop و Backoff
اگر app هر چند میلیثانیه برای دیتابیس یا API ناموجود retry و خطا را log کند، هم Disk و هم dependency را تحت فشار میگذارد. timeout، retry محدود، exponential backoff و jitter متناسب لازم است. خطاهای یکسان را میتوان aggregate یا rate-limit کرد، اما نباید رخداد مهم کاملاً مخفی شود. recovery و تعداد تلاش نهایی را به metric تبدیل کنید.
Healthcheckهای پرسروصدا
اگر هر health request در access log نوشته شود، فاصله کوتاه check میتواند حجم زیادی بسازد. endpoint health را کمهزینه نگه دارید و logging آن را با نیاز audit تنظیم کنید. حذف کامل log سلامت ممکن است تشخیص outage را سخت کند؛ sampling یا log جدا و metric موفق/ناموفق انتخاب متعادلتری است.
Payload و داده حساس
request body، header Authorization، cookie و secret نباید برای عیبیابی عمومی log شوند. علاوه بر ریسک امنیتی، payload حجم را چند برابر میکند. field allowlist، redaction و محدودیت طول تعریف کنید. stack trace برای هر retry تکراری لازم نیست؛ یک نمونه با correlation ID و شمارنده میتواند مفیدتر باشد. دسترسی و retention log را بخشی از سیاست حریم خصوصی بدانید.
ارسال به سامانه مرکزی
ارسال log به backend مستقل جستوجو و حفظ تاریخچه پس از خرابی host را بهتر میکند، اما queue، buffer و هزینه ingestion میخواهد. اگر مقصد قطع شود، driver sync ممکن است برنامه را block کند یا buffer محلی رشد کند؛ رفتار failure را در staging بررسی کنید. retention محلی کوتاه و مرکزی طولانیتر میتواند مناسب باشد، ولی duplication واقعی را اندازه بگیرید.
پاککردن اضطراری چه خطری دارد؟
ویرایش، truncate یا حذف مستقیم فایلهایی که Docker مدیریت میکند توصیه نمیشود؛ daemon ممکن است file descriptor باز و metadata خاص داشته باشد. ابتدا سرویس و driver را شناسایی کنید، headroom کمریسک از artifact یا cache تأییدشده بسازید و سپس recreate/restart کنترلشده انجام دهید. اگر log برای incident لازم است، نمونه و checksum را پیش از rotation حفظ کنید.
بعد از تغییر config چه کنیم؟
Compose را validate و سرویس هدف را با برنامه rollback recreate کنید. driver و options container تازه را inspect کنید. log آزمایشی بسازید و چرخش را در محیط امن ببینید؛ فقط منتظر پرشدن production نمانید. سلامت endpoint، command مشاهده log و agent مرکزی را تأیید کنید. راهنمای Compose production نکات rollout را توضیح میدهد.
مانیتورینگ مناسب
فضای آزاد، inode، نرخ رشد، حجم log به تفکیک سرویس، خطا در collector و سن آخرین log را پایش کنید. نبود log میتواند خرابی agent باشد، نه سلامت برنامه. Alert نزدیک ۱۰۰٪ دیر است؛ زمان تخمینی تا پرشدن و spike نرخ ingest ارزش بیشتری دارد. راهنمای مانیتورینگ owner و Runbook هشدار را پوشش میدهد.
Retention را از نرخ تولید حساب کنید
اگر سرویس در اوج ساعتی چند گیگابایت log میسازد، پنج فایل کوچک شاید فقط چند دقیقه تاریخ نگه دارد. ابتدا نرخ معمول و اوج را اندازه بگیرید، سپس حد محلی را با زمان تشخیص incident و ظرفیت Disk هماهنگ کنید. وجود backend مرکزی زمانی اجازه retention محلی کوتاهتر میدهد که تحویل log مانیتور و replay/buffer آن آزموده شده باشد. سهم همه containerها را جمع کنید؛ سقف مناسب برای یک سرویس اگر در دهها replica تکرار شود، باز هم host را پر میکند.
Multiline و Stack Trace
Stack trace چندخطی ممکن است در collector به رخدادهای جدا شکسته شود و هم جستوجو و هم شمارش را خراب کند. بهتر است برنامه structured log یکخطی با timestamp، level، service و correlation ID تولید کند، یا parser multiline دقیق داشته باشید. تبدیل کل exception به JSON حجیم بدون محدودیت نیز راهحل نیست. نمونه خطا و شمارنده تکرار، signal مفیدتری از هزار trace یکسان میدهد.
اشتباههای رایج
- حذف دستی فایل log فعال
- تنظیم rotation فقط در daemon و انتظار اثر روی container قدیمی
- بالابردن Disk بدون اصلاح retry loop
- ارسال payload و secret به log
- rotation بسیار کوتاه بدون backend مرکزی و از دسترفتن شواهد incident
- نادیدهگرفتن log فایل داخلی app
- اعتماد به running بودن collector بدون آزمون دریافت
چه زمانی کمک تخصصی لازم است؟
اگر Disk سریع پر میشود یا تغییر logging driver ممکن است observability production را قطع کند، ابتدا مسیر کامل تولید تا نگهداری log را نقشهبرداری کنید. پشتیبانی ساعتی DevOps میتواند log storm، rotation، collector و هشدار ظرفیت را بدون حذف شواهد ضروری اصلاح کند.
پرسشهای متداول
چرا بعد از تغییر daemon.json هنوز log قدیمی رشد میکند؟
container موجود معمولاً config جدید را خودکار نمیگیرد و باید با برنامه مناسب recreate شود.
آیا log rotation علت خطا را حل میکند؟
خیر؛ سقف storage را کنترل میکند. retry loop یا verbosity برنامه باید جدا اصلاح شود.
بهترین max-size چیست؟
عدد عمومی ندارد؛ نرخ log، زمان پاسخ incident و وجود backend مرکزی معیارند.
آیا میتوان همه logها را غیرفعال کرد؟
این کار تشخیص و audit را از بین میبرد. level، sampling، redaction و retention را هدفمند تنظیم کنید.