اگر فضای دیسک VPS بدون اینکه فایل بزرگی عمداً ذخیره کرده باشید مدام کم میشود، یکی از اولین جاهایی که باید بررسی کنید لاگ کانتینرهای Docker است. در نصبهای پیشفرض Docker، درایور json-file میتواند بدون محدودیت مشخص رشد کند و روی سرورهای پرترافیک یا سرویسهایی که خطای تکراری تولید میکنند، فایل لاگ یک کانتینر بهتنهایی چندین گیگابایت شود. در این راهنما ابتدا ثابت میکنیم مشکل واقعاً از Docker logs است، سپس درایور لاگ و مسیر فایل را پیدا میکنیم، برای local یا json-file Rotation میگذاریم، کانتینرها را بهدرستی Recreate میکنیم، نتیجه را Verify میکنیم و در پایان مسیر Rollback و Recovery را هم داریم.
چرا لاگ Docker میتواند دیسک VPS را پر کند؟
Docker خروجی stdout و stderr کانتینر را با Logging Driver مدیریت میکند. روی بسیاری از نصبها مقدار پیشفرض json-file است. این Driver برای سازگاری گسترده استفاده میشود، اما اگر برای آن max-size و max-file تعریف نشده باشد، فایل لاگ میتواند پیوسته بزرگ شود.
رشد لاگ معمولاً در این سناریوها شدیدتر است:
- وباپلیکیشن یا API که Access Log پرحجم روی stdout مینویسد؛
- Loop خطا در برنامه و چاپ چندباره Stack Trace؛
- Containerی که health check یا retry بسیار پرتکرار دارد؛
- سرویسهای Node.js، PHP، Python یا Java که سطح Log روی debug مانده است؛
- چند کانتینر روی VPS کمحجم که هر کدام چندصد مگابایت تا چند گیگابایت لاگ ساختهاند.
اگر مشکل شما «فایل حذف شده اما فضای دیسک آزاد نشده» است، آن سناریو متفاوت است و راهنمای رفع مشکل فضای دیسک با lsof +L1 را ببینید.
مرحله ۱: اول ثابت کنید واقعاً دیسک در حال پر شدن است
وضعیت filesystem را ببینید:
df -hTاگر پارتیشن روت یا /var نزدیک 90 تا 100 درصد است، مصرف دایرکتوریهای اصلی را مقایسه کنید:
sudo du -xhd1 /var 2>/dev/null | sort -hدر اغلب نصبهای rootful، داده Docker زیر /var/lib/docker قرار دارد. برای دیدن اندازه کلی آن:
sudo du -sh /var/lib/docker 2>/dev/nullاگر Docker Root Directory شما جای دیگری است، مسیر درست را از این دستور بخوانید:
docker info --format '{{.DockerRootDir}}'مرحله ۲: Logging Driver فعلی Docker را پیدا کنید
Driver پیشفرض daemon را ببینید:
docker info --format '{{.LoggingDriver}}'خروجی متداول:
json-fileیا ممکن است:
localبرای یک کانتینر مشخص هم تنظیم واقعی را بررسی کنید:
docker inspect -f '{{json .HostConfig.LogConfig}}' CONTAINER_NAMEو مسیر فایل لاگ را بگیرید:
docker inspect -f '{{.LogPath}}' CONTAINER_NAMEاگر از json-file استفاده میکنید، مسیر معمولاً چیزی زیر شاخه containers در Docker Root Directory است.
مرحله ۳: کانتینر یا لاگ حجیم را پیدا کنید
برای دیدن کانتینرهای فعال:
docker ps --format 'table {{.Names}} | {{.ID}} | {{.Status}}'سپس برای هر کانتینر مسیر لاگ را بخوانید و اندازه فایل را ببینید:
LOG=$(docker inspect -f '{{.LogPath}}' CONTAINER_NAME)
sudo ls -lh "$LOG"اگر تعداد کانتینرها زیاد است، این Loop دید خوبی میدهد:
for c in $(docker ps -aq); do
name=$(docker inspect -f '{{.Name}}' "$c" | sed 's#^/##')
log=$(docker inspect -f '{{.LogPath}}' "$c")
[ -n "$log" ] && sudo du -h "$log" 2>/dev/null | awk -v n="$name" '{print $1, n, $2}'
done | sort -hنکته: فایلهای داخلی Docker را بهصورت روتین با ابزارهای بیرونی rotate یا حذف نکنید. Docker خودش باید چرخه لاگ را مدیریت کند؛ دستکاری مستقیم فایل برای کار روزمره روش استاندارد نیست.
مرحله ۴: روش پیشنهادی برای سرور جدید؛ استفاده از local logging driver
Docker برای جلوگیری از تمامشدن فضای دیسک، Driver محلی local را برای سناریوهای عمومی گزینه مناسبی میداند چون Rotation داخلی دارد و فرمت ذخیرهسازی آن بهینهتر است.
فایل تنظیمات daemon را باز کنید:
sudo mkdir -p /etc/docker
sudo nano /etc/docker/daemon.jsonاگر فایل تازه است:
{
"log-driver": "local"
}قبل از restart، JSON را بررسی کنید:
sudo python3 -m json.tool /etc/docker/daemon.json >/dev/null && echo OKسپس Docker را restart کنید:
sudo systemctl restart dockerReadback:
docker info --format '{{.LoggingDriver}}'باید ببینید:
localمرحله ۵: اگر باید json-file بماند، Rotation را محدود کنید
اگر ابزار Log Collector یا Workflow شما به json-file وابسته است، میتوانید محدودیت اندازه و تعداد فایلها را فعال کنید:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}در این نمونه، هر فایل حداکثر حدود 10MB میشود و حداکثر سه فایل نگه داشته میشود. عدد مناسب را با توجه به ترافیک، مدت نگهداری لاگ و ظرفیت VPS انتخاب کنید.
مهم: مقدارهای داخل log-opts باید بهصورت string نوشته شوند؛ یعنی "3" و "10m"، نه عدد خام.
پس از ذخیره:
sudo python3 -m json.tool /etc/docker/daemon.json
sudo systemctl restart dockerمرحله ۶: چرا تغییر daemon.json روی کانتینرهای قبلی اعمال نمیشود؟
یکی از رایجترین اشتباهها این است که کاربر daemon.json را اصلاح میکند، Docker را restart میکند و انتظار دارد همه کانتینرهای موجود فوراً Driver جدید بگیرند. تنظیم Logging Driver هنگام ایجاد کانتینر ثبت میشود؛ بنابراین کانتینرهای موجود باید Recreate شوند.
برای Docker Compose:
docker compose config
docker compose up -d --force-recreateبعد از Recreate، Driver را Verify کنید:
docker inspect -f '{{json .HostConfig.LogConfig}}' CONTAINER_NAMEاگر از Docker Compose برای مدیریت چند کانتینر استفاده میکنید، Recreate را در زمان Maintenance Window انجام دهید تا اثر قطعی کنترل شود.
تنظیم Log Rotation فقط برای یک سرویس در Docker Compose
لازم نیست همیشه تنظیم را سراسری کنید. میتوانید فقط یک سرویس پرلاگ را محدود کنید:
services:
app:
image: your-image:latest
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"سپس:
docker compose config
docker compose up -d --force-recreate appVerify:
docker inspect -f '{{json .HostConfig.LogConfig}}' $(docker compose ps -q app)اگر دیسک همین حالا 100٪ شده چه کار کنیم؟
وقتی دیسک کاملاً پر است، قبل از هر کار ابتدا سرویس پرلاگ را شناسایی کنید. اگر امکان دارد لاگ برنامه را از داخل خود برنامه کم کنید یا سرویس را موقتاً متوقف کنید:
docker stop CONTAINER_NAMEبعد Rotation را درست تنظیم و کانتینر را Recreate کنید.
اگر بهخاطر 100٪ شدن دیسک حتی Recreate ممکن نیست، حذف یا truncate مستقیم فایل لاگ فقط یک راه Recovery اضطراری است، نه روش نگهداری روزمره. قبل از آن مسیر را دوباره با docker inspect Verify و کانتینر را متوقف کنید. برای محیط Production، Snapshot یا Backup و Maintenance Window داشته باشید.
اگر مشکل اصلی آزاد نشدن فضا بعد از حذف فایل است، مقاله بررسی فایلهای deleted ولی باز با lsof را اجرا کنید.
Verify نهایی بعد از اصلاح
بعد از تغییر فقط به «کانتینر بالا آمد» اکتفا نکنید. این مراحل را اجرا کنید:
- Driver پیشفرض Docker را بخوانید.
- Driver واقعی کانتینر Recreate شده را با
docker inspectبررسی کنید. - مسیر لاگ و اندازه آن را ثبت کنید.
- چند دقیقه یا چند ساعت بعد رشد فایل را دوباره اندازه بگیرید.
- فضای دیسک را با
df -hبررسی کنید. - Health Check و سرویس اصلی برنامه را تست کنید.
دستورهای سریع:
docker info --format '{{.LoggingDriver}}'
docker inspect -f '{{json .HostConfig.LogConfig}}' CONTAINER_NAME
docker inspect -f '{{.LogPath}}' CONTAINER_NAME
df -hT
docker psخطاهای رایج هنگام تنظیم Docker Log Rotation
- فقط restart کردن Docker: کانتینرهای موجود تنظیم Driver جدید را خودکار نمیگیرند و باید Recreate شوند.
- اشتباه در JSON: یک کاما یا کوتیشن اشتباه میتواند باعث Fail شدن Docker daemon شود. قبل از restart حتماً فایل را parse کنید.
- استفاده از عدد خام در log-opts: گزینههای
max-sizeوmax-fileرا بهصورت string بنویسید. - Rotation بیرونی روی فایل داخلی Docker: دستکاری فایل
*-json.logبا logrotate سیستم ممکن است با مدیریت فایل توسط Docker تداخل ایجاد کند. - ندیدن علت اصلی: Rotation فقط جلوی رشد بینهایت را میگیرد. اگر برنامه هزاران Error در دقیقه تولید میکند، ریشه مشکل Application باید اصلاح شود.
- پر بودن inode بهجای فضا: اگر
df -hخوب است اما No space left on device میگیرید،df -iرا هم ببینید.
برای دید بهتر روی مصرف CPU، RAM، Disk و Processها، مقاله دستورات مانیتورینگ سرورهای لینوکس مکمل مناسبی است.
Rollback و Recovery
قبل از تغییر، فایل قبلی را Backup بگیرید:
sudo cp -a /etc/docker/daemon.json /etc/docker/daemon.json.bak.$(date +%F-%H%M%S)اگر بعد از تغییر Docker بالا نیامد:
sudo systemctl status docker --no-pager
sudo journalctl -u docker -n 100 --no-pagerفایل JSON را دوباره Validate کنید:
sudo python3 -m json.tool /etc/docker/daemon.jsonاگر لازم است Backup را برگردانید و Docker را restart کنید:
sudo cp -a /etc/docker/daemon.json.bak.YYYY-MM-DD-HHMMSS /etc/docker/daemon.json
sudo systemctl restart dockerسپس با docker info و docker ps Readback بگیرید.
پیشنهاد عملی برای VPSهای Production
برای VPS معمولی که Log Collector خاصی ندارد، local انتخاب ساده و کمدردسرتری است. اگر به سازگاری json-file نیاز دارید، Rotation را صریحاً با max-size و max-file محدود کنید. علاوه بر آن:
- برای Disk Usage هشدار 75٪، 85٪ و 95٪ تعریف کنید؛
- سطح لاگ برنامه را روی Production از debug خارج کنید؛
- رشد لاگ کانتینرهای پرترافیک را جداگانه مانیتور کنید؛
- قبل از Recreate کانتینرهای مهم، Backup و Rollback Plan داشته باشید.
اگر برای اجرای چند کانتینر Production به منابع قابل ارتقا و دسترسی کامل سیستمعامل نیاز دارید، مشخصات سرور مجازی وانسرور را میتوانید بر اساس RAM، CPU و فضای دیسک موردنیاز بررسی کنید.
جمعبندی
پر شدن ناگهانی دیسک VPS همیشه به معنی کمبود واقعی Storage نیست؛ گاهی فقط یک کانتینر با Logging بدون محدودیت چندین گیگابایت فایل ساخته است. مسیر درست این است که ابتدا با df و docker inspect علت را ثابت کنید، Driver و LogPath را بخوانید، سپس local یا Rotation کنترلشده json-file را اعمال کنید. بعد از تغییر حتماً کانتینرهای قدیمی را Recreate کنید و با Readback واقعی مطمئن شوید تنظیم روی همان کانتینر اعمال شده است. در نهایت اندازه لاگ، سلامت سرویس و فضای دیسک را دوباره Verify کنید و Backup فایل daemon.json را برای Rollback نگه دارید.
منابع فنی
- Docker Docs: Configure logging drivers
- Docker Docs: Local logging driver
- Docker Docs: JSON File logging driver