پاکسازی کانتینرهای متوقف شده و منابع بلااستفاده
کانتینرهای متوقف شده و فایلسیستمهای بدون کانتینر را حذف میکند و فضای دیسک آزاد میکند.
🧩 دستور کلی
async pruneContainers(options = {})
شرح عملکرد
این متد تمام منابع غیرضروری را پاکسازی میکند. شامل:
- حذف کانتینرهای متوقف شده
- حذف blobs غیرمرجعشده
- حذف فایلسیستمهای orphaned در CONTAINERS_PATH
- تفکیک (unmount) و حذف فایلسیستمهای orphaned در OVERLAY
- logging عملیات حذف شده
مهم: این عملیات غیرقابل بازگشت است. قبل از اجرا مطمئن شوید که هیچ کانتینری مورد نیاز نیست.
ورودیها
| پارامتر | نوع | اجباری | توضیح |
|---|---|---|---|
options | Object | خیر | گزینههای 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());
}
}
نکات عملی
-
غیرقابل برگشت:
- prune عملیات غیرقابل بازگشت است
- قبل از اجرا مطمئن شوید
-
Stopped Containers:
- فقط کانتینرهای متوقف شده حذف میشود
- کانتینرهای running محفوظ میماند
-
Unreferenced Blobs:
- blobهایی که به هیچ کانتینری متعلق نیستند حذف میشود
- فضای دیسک قابل توجهی آزاد میشود
-
Orphaned Filesystems:
- فایلسیستمهای بدون کانتینر حذف میشود
- CONTAINERS_PATH و OVERLAY پاکسازی میشود
-
Database Cleanup:
- Records از دیتابیس حذف میشود
- blob references تمیز میشود
-
Timing:
- عملیات میتواند برای حجمهای بزرگ زمانبر باشد
- maintenance window بهترین زمان است
-
Safety:
- همیشه قبل از اجرا بکاپ بگیرید
- روی production با احتیاط انجام دهید
دنباله عملیات
- Validate options
- List all containers
- For each container: check if stopped
- Remove stopped containers
- Read rootfs layers (blobs)
- Find unreferenced blobs
- Delete blob records from DB
- Delete blob directories
- Read CONTAINERS_PATH directories
- Read OVERLAY directories
- Find orphaned directories
- Delete orphaned in CONTAINERS_PATH
- Unmount orphaned in OVERLAY
- Delete orphaned in OVERLAY
- Log removed items
- Return removed list
مرجع سریع
| وضعیت | کد | توضیح |
|---|---|---|
| موفق | 200 | prune تکمیل شد |
| هیچ نیست | 200 | هیچ item برای حذف |
| گزینه نامعتبر | 422 | OptionConflict |
| خطای لیست | 500 | ListFailure |
| خطای حذف | 500 | RemoveFailure |
| خطای FS | 500 | GenericFailure |
| Timeout | 408 | OperationTimeout |
| خطای DB | 500 | UpdateContainerStateFailure |
موارد استفاده
دورهای
// هر هفته یکبار
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