ذخیره ایمیج به فایل TAR
ایمیج را ذخیره کرده و فایل TAR ایجاد میکند.
🧩 دستور کلی
async saveImage(imageName, imageTags, filePath)
شرح عملکرد
این متد ایمیج را ذخیره کرده و فایل TAR ایجاد میکند. شامل:
- اعتبارسنجی پارامترهای ذخیره
- بررسی وجود تمام تگها
- کپی تصاویر به موقعیت موقت
- ایجاد آرشیو TAR
- مدیریت خطاهای فایل سیستم
- logging عملیات
مهم: تمام تگهای مشخص شده باید موجود باشند. ایمیج به صورت TAR ذخیره میشود و میتواند با فرمت OCI یا Docker باشد.
ورودیها
| پارامتر | نوع | اجباری | توضیح |
|---|---|---|---|
imageName | String | بله | نام ایمیج (مثلاً myapp, myrepo/myapp) |
imageTags | Array | بله | آرایهی تگهای ایمیج (مثلاً ['latest', 'v1.0']) |
filePath | String | بله | مسیر کامل فایل TAR خروجی (مثلاً /tmp/myapp.tar, /home/user/backup.tar.gz) |
خروجی
نوع: String
پیام موفقیت:
myapp has saved successfully to /tmp/myapp.tar
یا:
nginx has saved successfully to /home/user/backup.tar.gz
استثناها (Errors)
InvalidSaveImageParameters (422)
پیام: "Invalid save image parameters."
زمان رخ دادن: پارامترهای ذخیره نامعتبر باشند
جزئیات:
{
"type": "VALIDATION_ERROR",
"statusCode": 422,
"imageName": "invalid@image",
"imageTags": ["latest"],
"filePath": "/tmp/myapp.tar",
"error": "Image name contains invalid characters"
}
راهنمای حل:
- نام ایمیج: فقط حروف، اعداد، '-', '_', '/' مجاز
- تگها: آرایهی معتبر باشد
- مسیر فایل: معتبر و کامل باشد
ListImageTagsFailure (500)
پیام: "Failed to list image tags."
زمان رخ دادن: خطا در دریافت لیست تگهای ایمیج
جزئیات:
{
"type": "IMAGE_SERVICE_ERROR",
"statusCode": 500,
"imageName": "myapp",
"error": "Image service communication failed"
}
راهنمای حل:
- ImageManager را بررسی کنید
- اتصال سرویس را تأیید کنید
- لاگهای سیستم را بررسی کنید
ImageTagNotFound (404)
پیام: "Image tag not found."
زمان رخ دادن: یکی از تگهای مشخص شده موجود نیست
جزئیات:
{
"type": "NOT_FOUND",
"statusCode": 404,
"imageName": "myapp",
"imageTag": "v99.0",
"availableTags": ["latest", "v1.0", "v1.1"]
}
راهنمای حل:
- لیست تگهای موجود را بررسی کنید
- تگ صحیح را وارد کنید
listImages()استفاده کنید
CopyImageToTempFailure (500)
پیام: "Failed to copy image to temporary location."
زمان رخ دادن: خطا در کپی تصاویر به موقعیت موقت
جزئیات:
{
"type": "IMAGE_SERVICE_ERROR",
"statusCode": 500,
"imageName": "myapp",
"imageTags": ["latest", "v1.0"],
"error": "Image copy failed"
}
راهنمای حل:
- RegistryManager را بررسی کنید
- فضای دیسک کافی است؟
- اجازههای نوشتن در /tmp موجود است؟
SaveImagePermissionDenied (403)
پیام: "Permission denied to save image."
زمان رخ دادن: اجازههای نوشتن در مسیر فایل موجود نیست
جزئیات:
{
"type": "FILE_SYSTEM_ERROR",
"statusCode": 403,
"filePath": "/root/protected/myapp.tar",
"error": "Permission denied (EACCES)"
}
راهنمای حل:
- اجازههای فایل سیستم را بررسی کنید
- مسیری با اجازههای نوشتن استفاده کنید
- chmod یا chown استفاده کنید
InsufficientDiskSpaceForSave (507)
پیام: "Insufficient disk space to save image."
زمان رخ دادن: فضای دیسک برای ذخیره ایمیج کافی نیست
جزئیات:
{
"type": "FILE_SYSTEM_ERROR",
"statusCode": 507,
"filePath": "/tmp/myapp.tar",
"requiredSpace": "2.5 GB",
"availableSpace": "1.8 GB",
"error": "No space left on device (ENOSPC)"
}
راهنمای حل:
- فضای دیسک کافی کنید
- فایلهای غیر ضروری را حذف کنید
- مسیر دیسک دیگری استفاده کنید
ReadOnlyFileSystem (500)
پیام: "File system is read-only."
زمان رخ دادن: فایل سیستم read-only است
جزئیات:
{
"type": "FILE_SYSTEM_ERROR",
"statusCode": 500,
"filePath": "/mnt/readonly/myapp.tar",
"error": "Read-only file system (EROFS)"
}
راهنمای حل:
- فایل سیستم را remount کنید (writable)
- مسیر دیگری استفاده کنید
- اجازههای mount را بررسی کنید
SaveImageIOFailure (500)
پیام: "IO failure during image save."
زمان رخ دادن: خطای IO درخواندن یا نوشتن
جزئیات:
{
"type": "FILE_SYSTEM_ERROR",
"statusCode": 500,
"imageName": "myapp",
"filePath": "/tmp/myapp.tar",
"error": "IO exception"
}
راهنمای حل:
- سلامت هارد دیسک را بررسی کنید
- سیستم فایل را بررسی کنید (fsck)
- لاگهای سیستم را بررسی کنید
SaveImageFailure (500)
پیام: "Failed to save image."
زمان رخ دادن: خطای عمومی در ذخیره ایمیج
جزئیات:
{
"type": "IMAGE_SERVICE_ERROR",
"statusCode": 500,
"imageName": "myapp",
"imageTags": ["latest"],
"filePath": "/tmp/myapp.tar",
"error": "Save operation failed"
}
راهنمای حل:
- ImageManager را بررسی کنید
- لاگهای سیستم را بررسی کنید
- دوباره تلاش کنید
GenericFailure (500)
پیام: "Generic failure during image save."
زمان رخ دادن: خطای عمومی
جزئیات:
{
"type": "GENERIC_ERROR",
"statusCode": 500,
"error": "Image save failed"
}
راهنمای حل:
- سیستم لاگ را بررسی کنید
- تمام سرویسها را restart کنید
- دوباره تلاش کنید
مثالهای استفاده
مثال 1: Save ایمیج ساده
const K3Core = require('k3-core');
(async () => {
const k3 = new K3Core();
try {
const result = await k3.imageCore.saveImage(
'myapp',
['latest'],
'/tmp/myapp.tar'
);
console.log('Success:', result);
// Output: myapp has saved successfully to /tmp/myapp.tar
} catch (error) {
console.log('ERROR:', error.createFullMessage());
}
})();
مثال 2: Save چند تگ
(async () => {
const k3 = new K3Core();
try {
const result = await k3.imageCore.saveImage(
'nginx',
['latest', 'stable', 'alpine'],
'/home/user/nginx-backup.tar'
);
console.log('Save result:', result);
console.log('All tags saved: latest, stable, alpine');
} catch (error) {
console.log('ERROR: Failed to save image');
console.log(error.message);
}
})();
مثال 3: Save و verify
(async () => {
const k3 = new K3Core();
const fs = require('fs');
try {
// Step 1: Save
console.log('Saving image...');
const saveResult = await k3.imageCore.saveImage(
'alpine',
['latest'],
'/tmp/alpine-backup.tar'
);
console.log('Save result:', saveResult);
// Step 2: Verify
console.log('Verifying file...');
const stats = fs.statSync('/tmp/alpine-backup.tar');
console.log('File verified:');
console.log(` Size: ${(stats.size / 1024 / 1024).toFixed(2)} MB`);
console.log(` Created: ${stats.birthtime}`);
} catch (error) {
console.log('ERROR:', error.message);
}
})();
مثال 4: Save چند ایمیج
(async () => {
const k3 = new K3Core();
const imagesToSave = [
{ name: 'alpine', tags: ['latest'], path: '/tmp/alpine.tar' },
{ name: 'nginx', tags: ['latest', 'stable'], path: '/tmp/nginx.tar' },
{ name: 'node', tags: ['18', '20'], path: '/tmp/node.tar' }
];
const results = [];
for (const img of imagesToSave) {
try {
const result = await k3.imageCore.saveImage(img.name, img.tags, img.path);
results.push({
image: img.name,
tags: img.tags.join(', '),
status: 'success',
message: result
});
console.log(`✓ ${img.name} saved`);
} catch (error) {
results.push({
image: img.name,
tags: img.tags.join(', '),
status: 'failed',
error: error.message
});
console.log(`✗ Failed to save ${img.name}`);
}
}
console.log('\nSave Summary:');
console.table(results);
})();
مثال 5: Save با مدیریت خطاهای مختلف
(async () => {
const k3 = new K3Core();
const fs = require('fs');
const saveWithErrorHandling = async (imageName, imageTags, filePath) => {
try {
// Check disk space
const stats = fs.statSync(filePath.substring(0, filePath.lastIndexOf('/')));
console.log(`Available space: ${(stats.bavail * stats.bsize / 1024 / 1024 / 1024).toFixed(2)} GB`);
const result = await k3.imageCore.saveImage(imageName, imageTags, filePath);
return { success: true, message: result };
} catch (error) {
if (error.statusCode === 404) {
console.log(`ERROR: Tag not found for ${imageName}`);
return { success: false, error: 'Tag not found' };
} else if (error.statusCode === 403) {
console.log(`ERROR: Permission denied for ${filePath}`);
return { success: false, error: 'Permission denied' };
} else if (error.statusCode === 507) {
console.log(`ERROR: Insufficient disk space`);
return { success: false, error: 'Insufficient disk space' };
} else if (error.statusCode === 422) {
console.log('ERROR: Invalid parameters');
return { success: false, error: 'Invalid parameters' };
} else {
console.log(`ERROR: Save failed - ${error.message}`);
return { success: false, error: error.message };
}
}
};
const result = await saveWithErrorHandling('myapp', ['latest', 'v1.0'], '/tmp/myapp.tar');
console.log('Result:', result);
})();
مثال 6: Save و compress
(async () => {
const k3 = new K3Core();
try {
// Save
console.log('Saving image...');
const saveResult = await k3.imageCore.saveImage(
'postgres',
['latest', '15'],
'/tmp/postgres-backup.tar.gz'
);
console.log('Save result:', saveResult);
console.log('Image saved with compression');
} catch (error) {
console.log('ERROR:', error.message);
}
})();
مثال 7: Save برای backup
(async () => {
const k3 = new K3Core();
const fs = require('fs');
const path = require('path');
const createBackup = async (imageName, imageTags) => {
try {
// Create backup directory
const backupDir = '/backups/images';
if (!fs.existsSync(backupDir)) {
fs.mkdirSync(backupDir, { recursive: true });
}
// Generate backup filename
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const backupFile = path.join(backupDir, `${imageName}-${timestamp}.tar`);
console.log(`Creating backup: ${backupFile}`);
const result = await k3.imageCore.saveImage(imageName, imageTags, backupFile);
// Get file info
const stats = fs.statSync(backupFile);
console.log('Backup created:');
console.log(` File: ${backupFile}`);
console.log(` Size: ${(stats.size / 1024 / 1024).toFixed(2)} MB`);
console.log(` Tags: ${imageTags.join(', ')}`);
return { success: true, backupFile: backupFile, size: stats.size };
} catch (error) {
console.log('ERROR:', error.message);
return { success: false, error: error.message };
}
};
const backup = await createBackup('myapp', ['latest', 'v1.0']);
console.log('Backup result:', backup);
})();
مثال 8: Save و cleanup
(async () => {
const k3 = new K3Core();
const fs = require('fs');
try {
// Step 1: Save
console.log('Step 1: Saving image...');
const saveResult = await k3.imageCore.saveImage(
'old-service',
['latest'],
'/tmp/old-service-backup.tar'
);
console.log('✓ Image saved');
// Step 2: Verify backup
console.log('Step 2: Verifying backup...');
const stats = fs.statSync('/tmp/old-service-backup.tar');
console.log(`✓ Backup verified (${(stats.size / 1024 / 1024).toFixed(2)} MB)`);
// Step 3: Remove old image
console.log('Step 3: Removing old image...');
await k3.imageCore.removeAnImage('old-service', 'latest');
console.log('✓ Old image removed');
console.log('\n✓ Successfully backed up and removed old image');
} catch (error) {
console.log('ERROR:', error.message);
}
})();
الگوهای خطا و راهنمای حل
الگو 1: تگ یافت نشد
خطا: ImageTagNotFound (404)
راهنمای حل:
const saveWithTagCheck = async (imageName, imageTags, filePath) => {
try {
const result = await k3.imageCore.saveImage(imageName, imageTags, filePath);
return result;
} catch (error) {
if (error.statusCode === 404) {
console.log(`Tag not found for ${imageName}`);
// Get available tags
const images = await k3.imageCore.listImages({ image: imageName });
console.log('Available tags:');
images.forEach(img => console.log(` - ${img.Tag}`));
throw new Error(`Tag not found. Use valid tags from list above.`);
}
throw error;
}
};
await saveWithTagCheck('myapp', ['latest'], '/tmp/myapp.tar');
الگو 2: فضای دیسک ناکافی
خطا: InsufficientDiskSpaceForSave (507)
راهنمای حل:
const saveWithDiskCheck = async (imageName, imageTags, filePath) => {
const fs = require('fs');
const os = require('os');
try {
// Check available space
const dirPath = filePath.substring(0, filePath.lastIndexOf('/'));
const stats = fs.statSync(dirPath);
const availableSpace = stats.bavail * stats.bsize;
console.log(`Available space: ${(availableSpace / 1024 / 1024 / 1024).toFixed(2)} GB`);
if (availableSpace < 1 * 1024 * 1024 * 1024) {
console.log('WARNING: Less than 1GB available');
console.log('Attempting to free space...');
// Try to clean up temp directory
const tmpDir = '/tmp';
const files = fs.readdirSync(tmpDir).filter(f => f.endsWith('.tar'));
for (const file of files) {
fs.unlinkSync(`${tmpDir}/${file}`);
console.log(`Removed ${file}`);
}
}
const result = await k3.imageCore.saveImage(imageName, imageTags, filePath);
return { success: true, message: result };
} catch (error) {
if (error.statusCode === 507) {
console.log('ERROR: Insufficient disk space');
return { success: false, error: 'Insufficient disk space' };
}
throw error;
}
};
await saveWithDiskCheck('myapp', ['latest'], '/tmp/myapp.tar');
الگو 3: اجازههای فایل
خطا: SaveImagePermissionDenied (403)
راهنمای حل:
const saveWithPermissionCheck = async (imageName, imageTags, filePath) => {
const fs = require('fs');
try {
// Check if directory is writable
const dir = filePath.substring(0, filePath.lastIndexOf('/'));
try {
fs.accessSync(dir, fs.constants.W_OK);
console.log(`Directory is writable: ${dir}`);
} catch (err) {
console.log(`ERROR: Directory not writable: ${dir}`);
console.log('Available alternatives:');
console.log(' - /tmp (usually writable)');
console.log(' - /home/user (your home directory)');
throw new Error('Directory not writable');
}
const result = await k3.imageCore.saveImage(imageName, imageTags, filePath);
return { success: true, message: result };
} catch (error) {
if (error.statusCode === 403) {
console.log('ERROR: Permission denied');
return { success: false, error: 'Permission denied' };
}
throw error;
}
};
await saveWithPermissionCheck('myapp', ['latest'], '/tmp/myapp.tar');
الگو 4: Save با تتبع تغییرات
راهنمای حل:
class ImageSaveTracker {
constructor(k3) {
this.k3 = k3;
this.saves = [];
}
async save(imageName, imageTags, filePath) {
const startTime = Date.now();
const fs = require('fs');
try {
console.log(`Starting save: ${imageName} (${imageTags.join(', ')})`);
const result = await this.k3.imageCore.saveImage(imageName, imageTags, filePath);
const duration = Date.now() - startTime;
const fileSize = fs.statSync(filePath).size;
const speed = (fileSize / 1024 / 1024 / (duration / 1000)).toFixed(2);
this.saves.push({
image: imageName,
tags: imageTags.join(', '),
filePath: filePath,
fileSize: (fileSize / 1024 / 1024).toFixed(2) + ' MB',
duration: (duration / 1000).toFixed(2) + 's',
speed: speed + ' MB/s',
status: 'success',
timestamp: new Date()
});
console.log(`✓ Save completed in ${(duration / 1000).toFixed(2)}s (${speed} MB/s)`);
return result;
} catch (error) {
const duration = Date.now() - startTime;
this.saves.push({
image: imageName,
tags: imageTags.join(', '),
filePath: filePath,
duration: (duration / 1000).toFixed(2) + 's',
status: 'failed',
error: error.message,
timestamp: new Date()
});
console.log(`✗ Save failed after ${(duration / 1000).toFixed(2)}s`);
throw error;
}
}
getHistory() {
return this.saves;
}
printSummary() {
console.log('\n=== Save History ===');
console.table(this.saves);
}
}
const tracker = new ImageSaveTracker(k3);
await tracker.save('alpine', ['latest'], '/tmp/alpine.tar');
await tracker.save('nginx', ['latest', 'stable'], '/tmp/nginx.tar');
tracker.printSummary();
الگو 5: Save و restore workflow
راهنمای حل:
class ImageBackupManager {
constructor(k3) {
this.k3 = k3;
this.backupDir = '/backups/images';
}
async createBackup(imageName, imageTags) {
const fs = require('fs');
const path = require('path');
try {
// Create backup directory
if (!fs.existsSync(this.backupDir)) {
fs.mkdirSync(this.backupDir, { recursive: true });
}
// Generate filename
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const backupFile = path.join(this.backupDir, `${imageName}-${timestamp}.tar`);
console.log(`Creating backup: ${backupFile}`);
const result = await this.k3.imageCore.saveImage(imageName, imageTags, backupFile);
const stats = fs.statSync(backupFile);
console.log('Backup created:');
console.log(` Size: ${(stats.size / 1024 / 1024).toFixed(2)} MB`);
return { success: true, backupFile: backupFile };
} catch (error) {
console.log('ERROR:', error.message);
return { success: false, error: error.message };
}
}
async restoreBackup(backupFile, imageName) {
try {
console.log(`Restoring from: ${backupFile}`);
const result = await this.k3.imageCore.loadImage(imageName, backupFile);
console.log('Restore completed:');
console.log(` Image: ${imageName}`);
console.log(` From: ${backupFile}`);
return { success: true, message: result };
} catch (error) {
console.log('ERROR:', error.message);
return { success: false, error: error.message };
}
}
listBackups() {
const fs = require('fs');
if (!fs.existsSync(this.backupDir)) {
return [];
}
return fs.readdirSync(this.backupDir)
.filter(f => f.endsWith('.tar'))
.map(f => ({
filename: f,
path: `${this.backupDir}/${f}`,
size: (fs.statSync(`${this.backupDir}/${f}`).size / 1024 / 1024).toFixed(2) + ' MB'
}));
}
}
const backupMgr = new ImageBackupManager(k3);
await backupMgr.createBackup('myapp', ['latest', 'v1.0']);
console.log('Available backups:', backupMgr.listBackups());
await backupMgr.restoreBackup('/backups/images/myapp-2025-12-01T15-35-00.tar', 'myapp-restored');
نکات عملی
-
فضای دیسک:
- حداقل 2x اندازه ایمیج نیاز است
- موقت فایلها در /tmp ذخیره میشود
- بررسی فضای دیسک قبل از save
-
اجازههای فایل:
- مسیر باید writable باشد
- /tmp معمولاً writable است
- /root احتمالاً نیاز به sudo دارد
-
تغهای ایمیج:
- تمام تگها باید موجود باشند
- آرایه خالی مجاز نیست
- تکراری تگها مجاز است
-
Performance:
- بزرگ ایمیجها زمانبر هستند
- compression باعث افزایش زمان میشود
- SSD سریعتر از HDD است
-
Backup:
- timestamp استفاده کنید برای backup
- چند نسخه نگهداری کنید
- مسیر دایمالوصول استفاده کنید
-
موقت فایلها:
- /tmp میں موقت فایلها ایجاد میشود
- بعد از save حذف میشود
- اگر خطا رخ دهد، cleanup کنید
دنباله عملیات
- اعتبارسنجی پارامترها
- دریافت لیست تگهای ایمیج
- بررسی وجود هر تگ
- کپی تصاویر به موقعیت موقت
- ایجاد آرشیو TAR
- مدیریت خطاهای فایل سیستم
- Cleanup موقت فایلها
- Logging موفقیت
مرجع سریع
| وضعیت | کد | توضیح |
|---|---|---|
| موفق | 200 | Save موفق |
| پارامتر نامعتبر | 422 | InvalidSaveImageParameters |
| تگ یافت نشد | 404 | ImageTagNotFound |
| اجازه رد شد | 403 | SaveImagePermissionDenied |
| فضای کم | 507 | InsufficientDiskSpaceForSave |
| فایل سیستم read-only | 500 | ReadOnlyFileSystem |
| خطای IO | 500 | SaveImageIOFailure |
| خطای save | 500 | SaveImageFailure |
| خطای عمومی | 500 | GenericFailure |
موارد استفاده
Image Backup
const result = await saveImage('myapp', ['latest', 'v1.0'], '/backups/myapp.tar');
Archive Creation
const result = await saveImage('production-app', ['stable'], '/archive/app-v1.tar');
Distribution
const result = await saveImage('base-image', ['latest'], '/distribution/base.tar.gz');
Migration
const result = await saveImage('legacy-app', ['v2.0'], '/migration/legacy.tar');
نسخه: 1.3
تاریخ آپدیت: 10 آذرماه ۱۴۰۴
تیم توسعه: K3 Development Team