پرش به مطلب اصلی

پاکسازی کانتینرهای متوقف شده و منابع بلااستفاده

کانتینرهای متوقف شده و فایل‌سیستم‌های بدون کانتینر را حذف می‌کند و فضای دیسک آزاد می‌کند.


🧩 دستور کلی

async pruneContainers(options = {})

شرح عملکرد

این متد تمام منابع غیرضروری را پاکسازی می‌کند. شامل:

  • حذف کانتینرهای متوقف شده
  • حذف blobs غیرمرجع‌شده
  • حذف فایل‌سیستم‌های orphaned در CONTAINERS_PATH
  • تفکیک (unmount) و حذف فایل‌سیستم‌های orphaned در OVERLAY
  • logging عملیات حذف شده

مهم: این عملیات غیرقابل بازگشت است. قبل از اجرا مطمئن شوید که هیچ کانتینری مورد نیاز نیست.


ورودی‌ها

پارامترنوعاجباریتوضیح
optionsObjectخیرگزینه‌های prune (قابل توسعه)

خروجی

نوع: Array<String> (لیست hash IDs حذف شده)

نمونه خروجی:

[
"abc123def456",
"xyz789uvw012",
"def456ghi789"
]

استثناها (Errors)

OptionConflict (422)

پیام: "Failed to validate prune options."

زمان رخ دادن: گزینه‌های ورودی نامعتبر

جزئیات:

{
"type": "VALIDATION_ERROR",
"statusCode": 422,
"error": "Invalid schema"
}

راهنمای حل:

  • گزینه‌های ورودی را بررسی کنید

ListFailure (500)

پیام: "Failed to list containers for pruning."

زمان رخ دادن: خطا در دریافت لیست کانتینرها

جزئیات:

{
"type": "CONTAINER_SERVICE_ERROR",
"statusCode": 500,
"error": "List operation failed"
}

راهنمای حل:

  • سرویس container را بررسی کنید
  • دسترسی دیسک را تأیید کنید

FetchContainerState (500)

پیام: "Database error occurred while fetching container state."

زمان رخ دادن: خطا در دریافت اطلاعات کانتینر

جزئیات:

{
"type": "DB_ERROR",
"statusCode": 500,
"containerId": "abc123",
"error": "Database query failed"
}

راهنمای حل:

  • دیتابیس را بررسی کنید
  • اتصال دیتابیس را تأیید کنید

RemoveFailure (500)

پیام: "Failed to remove stopped container."

زمان رخ دادن: خطا در حذف کانتینر

جزئیات:

{
"type": "CONTAINER_SERVICE_ERROR",
"statusCode": 500,
"containerId": "abc123",
"error": "Remove operation failed"
}

راهنمای حل:

  • لاگ‌های runtime را بررسی کنید
  • منابع فایل‌سیستم را تأیید کنید

GenericFailure (500)

پیام: "Generic failure during blob or filesystem operations."

زمان رخ دادن: خطا در حذف blobs یا فایل‌سیستم‌ها

جزئیات:

{
"type": "GENERIC_ERROR",
"statusCode": 500,
"operation": "rmDir.overlay or readDir",
"error": "Filesystem operation failed"
}

راهنمای حل:

  • فضای دیسک را تأیید کنید
  • اجازه‌های فایل را بررسی کنید
  • lsof برای فایل‌های باز استفاده کنید

OperationTimeout (408)

پیام: "Filesystem operation timed out."

زمان رخ دادن: timeout در unmount یا حذف فایل‌سیستم

جزئیات:

{
"type": "TIMEOUT_ERROR",
"statusCode": 408,
"operation": "umountRootfs",
"timeout": 10000
}

راهنمای حل:

  • فایل‌های باز شده در overlay را بررسی کنید
  • فرآیند‌های مرتبط را متوقف کنید
  • دوباره prune را انجام دهید

UpdateContainerStateFailure (500)

پیام: "Failed to update container state in database."

زمان رخ دادن: خطا در حذف blob record

جزئیات:

{
"type": "DB_ERROR",
"statusCode": 500,
"blobHash": "abc123",
"error": "Database write failed"
}

راهنمای حل:

  • دیتابیس را بررسی کنید
  • فضای دیسک دیتابیس را تأیید کنید

مثال‌های استفاده

مثال 1: پاکسازی ساده

const K3Core = require('k3-core');

(async () => {
const k3 = new K3Core();

try {
const removed = await k3.containerCore.pruneContainers({});
console.log(`Pruned containers: ${removed.length}`);
console.log('Removed hashes:', removed);
} catch (error) {
console.log(error.createFullMessage());
}
})();

مثال 2: پاکسازی و بررسی آزاد شده فضا

(async () => {
const k3 = new K3Core();

try {
console.log('Starting prune operation...');
const removed = await k3.containerCore.pruneContainers({});

console.log(`Removed ${removed.length} items`);

if (removed.length > 0) {
console.log('Removed items:');
removed.forEach((item, index) => {
console.log(` ${index + 1}. ${item}`);
});
} else {
console.log('No items to prune');
}

} catch (error) {
console.log(error.createFullMessage());
}
})();

مثال 3: پاکسازی دوره‌ای

(async () => {
const k3 = new K3Core();

const pruneIntervalHours = 24;
const pruneIntervalMs = pruneIntervalHours * 60 * 60 * 1000;

setInterval(async () => {
try {
console.log(`[${new Date().toISOString()}] Running scheduled prune...`);
const removed = await k3.containerCore.pruneContainers({});
console.log(`[${new Date().toISOString()}] Pruned ${removed.length} items`);
} catch (error) {
console.error(`[${new Date().toISOString()}] Prune failed:`, error.message);
}
}, pruneIntervalMs);
})();

مثال 4: پاکسازی با بررسی وضعیت کانتینرها قبل

(async () => {
const k3 = new K3Core();

try {
// Step 1: بررسی وضعیت کانتینرها
const containers = await k3.containerCore.listContainers({ all: true });
console.log(`Total containers: ${containers.length}`);

const stopped = containers.filter(c =>
String(c.status || c.state || '').includes('stopped')
);
console.log(`Stopped containers: ${stopped.length}`);

if (stopped.length === 0) {
console.log('No stopped containers to prune');
return;
}

console.log('Stopped containers:');
stopped.forEach(c => {
console.log(` - ${c.name} (${c.id})`);
});

// Step 2: تایید و prune
console.log('\nStarting prune operation...');
const removed = await k3.containerCore.pruneContainers({});

console.log(`\nPruned successfully: ${removed.length} items removed`);

} catch (error) {
console.log(error.createFullMessage());
}
})();

مثال 6: پاکسازی و گزارش دهی

(async () => {
const k3 = new K3Core();

try {
const startTime = Date.now();
console.log('Prune operation started at', new Date().toISOString());

const removed = await k3.containerCore.pruneContainers({});

const duration = Date.now() - startTime;

console.log('Prune operation completed');
console.log(`Duration: ${duration}ms`);
console.log(`Items removed: ${removed.length}`);
console.log(`Average per item: ${(duration / removed.length).toFixed(2)}ms`);

if (removed.length > 0) {
console.log('\nRemoved items:');
removed.slice(0, 5).forEach(item => {
console.log(` - ${item}`);
});
if (removed.length > 5) {
console.log(` ... and ${removed.length - 5} more`);
}
}

} catch (error) {
console.log('Prune failed:', error.message);
}
})();

مثال 7: پاکسازی عمیق (safe prune)

(async () => {
const k3 = new K3Core();

try {
// Step 1: بررسی
console.log('Checking system state before prune...');
const containers = await k3.containerCore.listContainers({ all: true });
const running = containers.filter(c =>
String(c.status || c.state || '').includes('running')
);

if (running.length > 0) {
console.log(`Warning: ${running.length} containers still running`);
console.log('These will not be pruned.');
}

// Step 2: پاکسازی
console.log('\nStarting safe prune...');
const removed = await k3.containerCore.pruneContainers({});

// Step 3: تأیید
console.log('\nVerifying prune results...');
const containersAfter = await k3.containerCore.listContainers({ all: true });

console.log(`\nPrune Results:`);
console.log(` Removed items: ${removed.length}`);
console.log(` Containers before: ${containers.length}`);
console.log(` Containers after: ${containersAfter.length}`);
console.log(` Difference: ${containers.length - containersAfter.length}`);

} catch (error) {
console.log('Safe prune failed:', error.message);
}
})();

الگوهای خطا و راهنمای حل

الگو 1: نیستن کانتینری برای prune

خطا: ListFailure یا هیچی

راهنمای حل:

try {
const removed = await k3.containerCore.pruneContainers({});

if (removed.length === 0) {
console.log('No containers to prune - system is clean');
} else {
console.log(`Pruned ${removed.length} items`);
}
} catch (error) {
if (error.message.includes('No containers found')) {
console.log('No containers exist - nothing to prune');
} else {
console.log(error.createFullMessage());
}
}

الگو 2: خطای فایل‌سیستم

خطا: GenericFailure (500)

راهنمای حل:

try {
const removed = await k3.containerCore.pruneContainers({});
console.log(`Successfully pruned ${removed.length} items`);
} catch (error) {
if (error.message.includes('rmDir') || error.message.includes('umount')) {
console.log('Filesystem error - checking permissions and space...');

// بررسی فضای دیسک
const fs = require('fs');
const diskUsage = require('disk-usage');

try {
const usage = diskUsage.check('/');
console.log(`Disk space: ${usage.available} bytes available`);
} catch (e) {
console.log('Could not check disk space');
}

// تلاش مجدد بعد از مدتی
console.log('Retrying after 5 seconds...');
await new Promise(resolve => setTimeout(resolve, 5000));

const removed = await k3.containerCore.pruneContainers({});
console.log(`Retry successful: ${removed.length} items pruned`);
} else {
console.log(error.createFullMessage());
}
}

نکات عملی

  1. غیرقابل برگشت:

    • prune عملیات غیرقابل بازگشت است
    • قبل از اجرا مطمئن شوید
  2. Stopped Containers:

    • فقط کانتینرهای متوقف شده حذف می‌شود
    • کانتینرهای running محفوظ می‌ماند
  3. Unreferenced Blobs:

    • blob‌هایی که به هیچ کانتینری متعلق نیستند حذف می‌شود
    • فضای دیسک قابل توجهی آزاد می‌شود
  4. Orphaned Filesystems:

    • فایل‌سیستم‌های بدون کانتینر حذف می‌شود
    • CONTAINERS_PATH و OVERLAY پاکسازی می‌شود
  5. Database Cleanup:

    • Records از دیتابیس حذف می‌شود
    • blob references تمیز می‌شود
  6. Timing:

    • عملیات می‌تواند برای حجم‌های بزرگ زمان‌بر باشد
    • maintenance window بهترین زمان است
  7. Safety:

    • همیشه قبل از اجرا بکاپ بگیرید
    • روی production با احتیاط انجام دهید

دنباله عملیات

  1. Validate options
  2. List all containers
  3. For each container: check if stopped
  4. Remove stopped containers
  5. Read rootfs layers (blobs)
  6. Find unreferenced blobs
  7. Delete blob records from DB
  8. Delete blob directories
  9. Read CONTAINERS_PATH directories
  10. Read OVERLAY directories
  11. Find orphaned directories
  12. Delete orphaned in CONTAINERS_PATH
  13. Unmount orphaned in OVERLAY
  14. Delete orphaned in OVERLAY
  15. Log removed items
  16. Return removed list

مرجع سریع

وضعیتکدتوضیح
موفق200prune تکمیل شد
هیچ نیست200هیچ item برای حذف
گزینه نامعتبر422OptionConflict
خطای لیست500ListFailure
خطای حذف500RemoveFailure
خطای FS500GenericFailure
Timeout408OperationTimeout
خطای DB500UpdateContainerStateFailure

موارد استفاده

دوره‌ای

// هر هفته یکبار
setInterval(() => pruneContainers(), 7 * 24 * 60 * 60 * 1000);

بعد از حذف جمعی

// بعد از removeContainer چندین بار
await pruneContainers();

Cleanup قبل upgrade

// قبل از system upgrade
await pruneContainers();

Low disk space recovery

// هنگام کمبود فضا
await pruneContainers();

نسخه: 1.3
تاریخ آپدیت: 9 آذرماه ۱۴۰۴
تیم توسعه: K3 Development Team