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

ذخیره ایمیج به فایل TAR

ایمیج را ذخیره کرده و فایل TAR ایجاد می‌کند.


🧩 دستور کلی

async saveImage(imageName, imageTags, filePath)

شرح عملکرد

این متد ایمیج را ذخیره کرده و فایل TAR ایجاد می‌کند. شامل:

  • اعتبارسنجی پارامترهای ذخیره
  • بررسی وجود تمام تگ‌ها
  • کپی تصاویر به موقعیت موقت
  • ایجاد آرشیو TAR
  • مدیریت خطاهای فایل سیستم
  • logging عملیات

مهم: تمام تگ‌های مشخص شده باید موجود باشند. ایمیج به صورت TAR ذخیره می‌شود و می‌تواند با فرمت OCI یا Docker باشد.


ورودی‌ها

پارامترنوعاجباریتوضیح
imageNameStringبلهنام ایمیج (مثلاً myapp, myrepo/myapp)
imageTagsArrayبلهآرایه‌ی تگ‌های ایمیج (مثلاً ['latest', 'v1.0'])
filePathStringبلهمسیر کامل فایل 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');

نکات عملی

  1. فضای دیسک:

    • حداقل 2x اندازه ایمیج نیاز است
    • موقت فایل‌ها در /tmp ذخیره می‌شود
    • بررسی فضای دیسک قبل از save
  2. اجازه‌های فایل:

    • مسیر باید writable باشد
    • /tmp معمولاً writable است
    • /root احتمالاً نیاز به sudo دارد
  3. تغ‌های ایمیج:

    • تمام تگ‌ها باید موجود باشند
    • آرایه خالی مجاز نیست
    • تکراری تگ‌ها مجاز است
  4. Performance:

    • بزرگ ایمیج‌ها زمان‌بر هستند
    • compression باعث افزایش زمان می‌شود
    • SSD سریع‌تر از HDD است
  5. Backup:

    • timestamp استفاده کنید برای backup
    • چند نسخه نگه‌داری کنید
    • مسیر دایم‌الوصول استفاده کنید
  6. موقت فایل‌ها:

    • /tmp میں موقت فایل‌ها ایجاد می‌شود
    • بعد از save حذف می‌شود
    • اگر خطا رخ دهد، cleanup کنید

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

  1. اعتبارسنجی پارامترها
  2. دریافت لیست تگ‌های ایمیج
  3. بررسی وجود هر تگ
  4. کپی تصاویر به موقعیت موقت
  5. ایجاد آرشیو TAR
  6. مدیریت خطاهای فایل سیستم
  7. Cleanup موقت فایل‌ها
  8. Logging موفقیت

مرجع سریع

وضعیتکدتوضیح
موفق200Save موفق
پارامتر نامعتبر422InvalidSaveImageParameters
تگ یافت نشد404ImageTagNotFound
اجازه رد شد403SaveImagePermissionDenied
فضای کم507InsufficientDiskSpaceForSave
فایل سیستم read-only500ReadOnlyFileSystem
خطای IO500SaveImageIOFailure
خطای save500SaveImageFailure
خطای عمومی500GenericFailure

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

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