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

دانلود ایمیج

ایمیج را دور دانلود کرده و در رجیستری محلی ذخیره می‌کند.


🧩 دستور کلی

async pullAnImage(imageName, imageTag = "latest", optionsObject = {})

شرح عملکرد

این متد ایمیج را دور (مانند Docker Hub) دانلود می‌کند و در محل محلی ذخیره می‌کند. شامل:

  • اعتبارسنجی نام ایمیج و تگ
  • بررسی وجود ایمیج (جلوگیری از دانلود تکراری)
  • ایجاد دایرکتوری ایمیج اگر نیاز باشد
  • بررسی اطلاعات ایمیج از رجیستری
  • بررسی فضای دیسک دستیاب
  • دانلود ایمیج با استفاده از skopeo
  • یافتن blob‌های ایمیج
  • ایجاد رکوردهای blob در پایگاه داده
  • محاسبه اندازه ایمیج
  • دریافت تاریخچه ایمیج
  • ایجاد رکورد ایمیج در پایگاه داده
  • logging عملیات

مهم: Pull عملیات زمان‌بر است و نیاز به اتصال شبکه دارد. فضای دیسک کافی باید موجود باشد (حداقل 2.5 برابر اندازه ایمیج).


ورودی‌ها

پارامترنوعاجباریتوضیح
imageNameStringبلهنام ایمیج (مثلاً alpine, nginx, myrepo/myimage)
imageTagStringخیرنام تگ (پیش‌فرض: latest)
optionsObjectObjectخیرگزینه‌های اضافی (مثل proxy, credentials)

خروجی

نوع: String

پیام موفقیت:

alpine:latest has pulled successfully

یا:

nginx:1.25 has pulled successfully

استثناها (Errors)

InvalidImageNameOrTag (422)

پیام: "Invalid image name or tag format."

زمان رخ دادن: نام ایمیج یا تگ نامعتبر باشد

جزئیات:

{
"type": "VALIDATION_ERROR",
"statusCode": 422,
"imageName": "invalid@image",
"imageTag": "latest",
"error": "Image name contains invalid characters"
}

راهنمای حل:

  • نام ایمیج: فقط حروف، اعداد، '-', '_', '/' مجاز
  • تگ: فقط حروف، اعداد، '.', '-' مجاز
  • فرمت صحیح: imageName:tag یا repo/imageName:tag

ImageAlreadyExists (409)

پیام: "Image already exists in local registry."

زمان رخ دادن: ایمیج با همین نام و تگ قبلاً دانلود شده است

جزئیات:

{
"type": "INVALID_STATE_ERROR",
"statusCode": 409,
"imageName": "alpine",
"imageTag": "latest",
"error": "Image already exists"
}

راهنمای حل:

  • ایمیج قبلاً دانلود شده است
  • برای بروزرسانی، ابتدا ایمیج قدیم را حذف کنید
  • یا تگ متفاوتی استفاده کنید

FetchImageState (500)

پیام: "Failed to check image state in database."

زمان رخ دادن: خطا در بررسی وجود ایمیج در DB

جزئیات:

{
"type": "DB_ERROR",
"statusCode": 500,
"imageName": "nginx",
"imageTag": "latest",
"error": "Database query failed"
}

راهنمای حل:

  • اتصال دیتابیس را بررسی کنید
  • دیتابیس را restart کنید
  • لاگ‌های DB را بررسی کنید

CreateImageDirectoryFailure (500)

پیام: "Failed to create image directory."

زمان رخ دادن: خطا در ایجاد دایرکتوری ایمیج

جزئیات:

{
"type": "IMAGE_SERVICE_ERROR",
"statusCode": 500,
"imageName": "ubuntu",
"error": "Directory creation failed"
}

راهنمای حل:

  • اجازه‌های فایل سیستم را بررسی کنید
  • مسیر /var/lib/k3/images موجود است؟
  • فضای دیسک کافی است یا خیر؟

RegistryInspectFailure (500)

پیام: "Failed to inspect image from remote registry."

زمان رخ دادن: خطا در بررسی اطلاعات ایمیج از رجیستری دور

جزئیات:

{
"type": "NETWORK_ERROR",
"statusCode": 500,
"imageName": "nginx",
"imageTag": "latest",
"registry": "docker.io",
"error": "Registry connection failed"
}

راهنمای حل:

  • اتصال اینترنت را بررسی کنید
  • رجیستری دستیاب است یا خیر؟
  • نام ایمیج درست است؟
  • firewall یا proxy مسدود نمی‌کند؟

InsufficientDiskSpace (507)

پیام: "Insufficient disk space to pull image."

زمان رخ دادن: فضای دیسک برای دانلود ایمیج کافی نیست

جزئیات:

{
"type": "IMAGE_SERVICE_ERROR",
"statusCode": 507,
"imageName": "large-image",
"imageTag": "latest",
"requiredSpace": "2.5 GB",
"availableSpace": "1.8 GB",
"error": "Not enough disk space"
}

راهنمای حل:

  • فضای دیسک کافی کنید (حداقل 2.5 برابر اندازه ایمیج)
  • ایمیج‌های قدیم را حذف کنید
  • دسک دیگری استفاده کنید

ImagePullFailure (500)

پیام: "Failed to pull image from registry."

زمان رخ دادن: خطا در دانلود ایمیج

جزئیات:

{
"type": "NETWORK_ERROR",
"statusCode": 500,
"imageName": "myapp",
"imageTag": "v1.0",
"error": "Image not found in registry"
}

راهنمای حل:

  • ایمیج در رجیستری موجود است یا خیر؟
  • نام ایمیج و تگ درست است؟
  • اتصال رجیستری برقرار است؟
  • authentication diperlukan کنید؟

FindBlobsFailure (500)

پیام: "Failed to find image blobs."

زمان رخ دادن: خطا در یافتن blob‌های ایمیج

جزئیات:

{
"type": "IMAGE_SERVICE_ERROR",
"statusCode": 500,
"imageName": "postgres",
"imageTag": "15",
"error": "Blob scanning failed"
}

راهنمای حل:

  • دایرکتوری ایمیج را بررسی کنید
  • فایل‌های blob موجود است؟
  • دقیق‌ترین را دنبال کنید

CreateImageBlobFailure (500)

پیام: "Failed to create blob record in database."

زمان رخ دادن: خطا در ایجاد رکورد blob در DB

جزئیات:

{
"type": "DB_ERROR",
"statusCode": 500,
"imageName": "node",
"imageTag": "18",
"blobCount": 5,
"error": "Database write failed"
}

راهنمای حل:

  • اتصال دیتابیس را بررسی کنید
  • فضای دیسک DB کافی است؟
  • دیتابیس را restart کنید

CalculateImageSizeFailure (500)

پیام: "Failed to calculate image size."

زمان رخ دادن: خطا در محاسبه اندازه ایمیج

جزئیات:

{
"type": "IMAGE_SERVICE_ERROR",
"statusCode": 500,
"imageName": "mysql",
"imageTag": "8.0",
"error": "Size calculation failed"
}

راهنمای حل:

  • دایرکتوری ایمیج موجود است؟
  • فایل‌ها خراب نشده‌اند؟
  • اجازه‌های خواندن موجود است؟

FetchImageHistoryFailure (500)

پیام: "Failed to fetch image history."

زمان رخ دادن: خطا در دریافت تاریخچه ایمیج

جزئیات:

{
"type": "IMAGE_SERVICE_ERROR",
"statusCode": 500,
"imageName": "redis",
"imageTag": "latest",
"error": "History fetch failed"
}

راهنمای حل:

  • ImageManager را بررسی کنید
  • metadata ایمیج موجود است؟
  • دوباره تلاش کنید

CreateImageRecordFailure (500)

پیام: "Failed to create image record in database."

زمان رخ دادن: خطا در ایجاد رکورد ایمیج در DB

جزئیات:

{
"type": "DB_ERROR",
"statusCode": 500,
"imageName": "app",
"imageTag": "1.0",
"error": "Database write failed"
}

راهنمای حل:

  • اتصال دیتابیس را بررسی کنید
  • دیتابیس را restart کنید
  • transaction logs را بررسی کنید

GenericFailure (500)

پیام: "Generic failure during image pull."

زمان رخ دادن: خطای عمومی

جزئیات:

{
"type": "GENERIC_ERROR",
"statusCode": 500,
"error": "Image pull failed"
}

راهنمای حل:

  • سیستم لاگ را بررسی کنید
  • تمام سرویس‌ها را restart کنید
  • دوباره تلاش کنید

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

مثال 1: دانلود ایمیج با تگ پیش‌فرض

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

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

try {
const result = await k3.imageCore.pullAnImage('alpine');
console.log(result);
// Output: alpine:latest has pulled successfully
} catch (error) {
console.log(error.createFullMessage());
}
})();

مثال 2: دانلود ایمیج با تگ خاص

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

try {
const result = await k3.imageCore.pullAnImage('nginx', '1.25');
console.log(result);
// Output: nginx:1.25 has pulled successfully
} catch (error) {
console.log(error.createFullMessage());
}
})();

مثال 3: دانلود ایمیج از رجیستری خاص

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

try {
const result = await k3.imageCore.pullAnImage('myregistry/myapp', 'v1.0');
console.log(result);
// Output: myregistry/myapp:v1.0 has pulled successfully
} catch (error) {
console.log(error.createFullMessage());
}
})();

مثال 4: دانلود ایمیج با بررسی فضای دیسک

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

try {
const result = await k3.imageCore.pullAnImage('ubuntu', '22.04');
console.log('Pull successful:', result);
} catch (error) {
if (error.statusCode === 507) {
console.log('ERROR: Not enough disk space');
console.log('Required:', error.requiredSpace);
console.log('Available:', error.availableSpace);
} else {
console.log('Pull failed:', error.message);
}
}
})();

مثال 5: دانلود چند ایمیج

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

const images = [
{ name: 'alpine', tag: 'latest' },
{ name: 'nginx', tag: '1.25' },
{ name: 'node', tag: '18' }
];

const results = [];

for (const img of images) {
try {
const result = await k3.imageCore.pullAnImage(img.name, img.tag);
results.push({ status: 'success', message: result });
console.log(`${result}`);
} catch (error) {
results.push({ status: 'failed', error: error.message });
console.log(`✗ Failed to pull ${img.name}:${img.tag} - ${error.message}`);
}
}

console.log('\nSummary:');
const successful = results.filter(r => r.status === 'success').length;
const failed = results.filter(r => r.status === 'failed').length;
console.log(`Successful: ${successful}, Failed: ${failed}`);
})();

مثال 6: دانلود با بررسی موجودیت قبلی

(async () => {
const k3 = new K3Core();
const imageName = 'postgres';
const imageTag = '15';

try {
// بررسی اگر ایمیج قبلاً وجود دارد
const images = await k3.imageCore.listImages({
image: imageName,
tag: imageTag
});

if (images.length > 0) {
console.log(`Image ${imageName}:${imageTag} already exists`);
console.log('Skipping pull...');
return;
}

// دانلود ایمیج
const result = await k3.imageCore.pullAnImage(imageName, imageTag);
console.log('Pull result:', result);
} catch (error) {
console.log('ERROR:', error.message);
}
})();

مثال 7: دانلود ایمیج و ایجاد کانتینر

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

try {
// Pull ایمیج
const pullResult = await k3.imageCore.pullAnImage('alpine', 'latest');
console.log('Pull:', pullResult);

// Create و اجرای کانتینر
const containerResult = await k3.containerCore.runContainer({
containerId: 'my-alpine',
image: 'alpine',
tag: 'latest'
});

console.log('Container created:', containerResult);
} catch (error) {
console.log('ERROR:', error.createFullMessage());
}
})();

مثال 8: دانلود ایمیج با مدیریت خطاهای رایج

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

const pullImageWithErrorHandling = async (name, tag) => {
try {
const result = await k3.imageCore.pullAnImage(name, tag);
return { success: true, message: result };
} catch (error) {
if (error.statusCode === 409) {
console.log(`WARNING: Image ${name}:${tag} already exists`);
return { success: true, skipped: true, reason: 'Already exists' };
} else if (error.statusCode === 507) {
console.log(`ERROR: Not enough disk space for ${name}:${tag}`);
console.log(`Need: ${error.requiredSpace}, Have: ${error.availableSpace}`);
return { success: false, error: 'Insufficient disk space' };
} else if (error.statusCode === 500 && error.message.includes('not found')) {
console.log(`ERROR: Image ${name}:${tag} not found in registry`);
return { success: false, error: 'Image not found' };
} else {
console.log(`ERROR: Failed to pull ${name}:${tag}`);
return { success: false, error: error.message };
}
}
};

const result = await pullImageWithErrorHandling('myapp', 'v1.0');
console.log('Final result:', result);
})();

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

الگو 1: ایمیج قبلاً موجود است

خطا: ImageAlreadyExists (409)

راهنمای حل:

const pullOrSkip = async (imageName, imageTag) => {
try {
const result = await k3.imageCore.pullAnImage(imageName, imageTag);
console.log('Pull successful:', result);
return true;
} catch (error) {
if (error.statusCode === 409) {
console.log(`Image ${imageName}:${imageTag} already exists locally`);

// اگر می‌خواهید بروزرسانی کنید:
console.log('Removing existing image...');
await k3.imageCore.removeAnImage(imageName, imageTag);

console.log('Pulling fresh image...');
const result = await k3.imageCore.pullAnImage(imageName, imageTag);
console.log('Pull successful:', result);
return true;
}
throw error;
}
};

await pullOrSkip('nginx', 'latest');

الگو 2: فضای دیسک ناکافی

خطا: InsufficientDiskSpace (507)

راهنمای حل:

const pullWithDiskCheck = async (imageName, imageTag) => {
try {
const result = await k3.imageCore.pullAnImage(imageName, imageTag);
return { success: true, message: result };
} catch (error) {
if (error.statusCode === 507) {
console.log('Insufficient disk space detected');
console.log(`Required: ${error.requiredSpace}`);
console.log(`Available: ${error.availableSpace}`);

// Cleanup old images
console.log('Attempting to free space...');
const images = await k3.imageCore.listImages({});

// Remove oldest or largest images
for (const img of images) {
if (shouldRemove(img)) {
await k3.imageCore.removeAnImage(img.Name, img.Tag);
console.log(`Removed ${img.Name}:${img.Tag}`);
}
}

// Retry pull
console.log('Retrying pull...');
const retryResult = await k3.imageCore.pullAnImage(imageName, imageTag);
return { success: true, message: retryResult, cleanedUp: true };
}
throw error;
}
};

const result = await pullWithDiskCheck('large-app', 'v1.0');

الگو 3: ایمیج در رجیستری یافت نشد

خطا: ImagePullFailure (500)

راهنمای حل:

const pullWithFallback = async (imageName, imageTag) => {
try {
const result = await k3.imageCore.pullAnImage(imageName, imageTag);
console.log('Pull successful:', result);
return result;
} catch (error) {
if (error.message.includes('not found')) {
console.log(`Image ${imageName}:${imageTag} not found`);
console.log('Trying alternative sources...');

// Try different registry
const alternatives = [
{ name: 'gcr.io/' + imageName, tag: imageTag },
{ name: 'quay.io/' + imageName, tag: imageTag },
{ name: imageName, tag: 'v' + imageTag } // try different tag
];

for (const alt of alternatives) {
try {
const result = await k3.imageCore.pullAnImage(alt.name, alt.tag);
console.log(`Found alternative: ${alt.name}:${alt.tag}`);
return result;
} catch (e) {
console.log(`Alternative ${alt.name}:${alt.tag} not found`);
}
}

throw new Error(`Could not find ${imageName}:${imageTag} anywhere`);
}
throw error;
}
};

await pullWithFallback('myapp', 'latest');

الگو 4: اتصال رجیستری قطع شد

خطا: RegistryInspectFailure (500)

راهنمای حل:

const pullWithRetry = async (imageName, imageTag, maxRetries = 3) => {
let lastError;

for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
console.log(`Pull attempt ${attempt}/${maxRetries}: ${imageName}:${imageTag}`);
const result = await k3.imageCore.pullAnImage(imageName, imageTag);
console.log('Pull successful:', result);
return result;
} catch (error) {
lastError = error;

if (attempt < maxRetries) {
const waitTime = Math.pow(2, attempt) * 1000; // Exponential backoff
console.log(`Pull failed: ${error.message}`);
console.log(`Retrying in ${waitTime / 1000} seconds...`);

await new Promise(resolve => setTimeout(resolve, waitTime));
}
}
}

throw lastError;
};

const result = await pullWithRetry('nginx', '1.25');

الگو 5: دانلود همزمان چند ایمیج با مدیریت منابع

راهنمای حل:

class ImagePullManager {
constructor(k3, maxConcurrent = 2) {
this.k3 = k3;
this.maxConcurrent = maxConcurrent;
this.queue = [];
this.active = 0;
this.results = [];
}

async pull(imageName, imageTag) {
return new Promise((resolve) => {
this.queue.push({ imageName, imageTag, resolve });
this.processQueue();
});
}

async processQueue() {
while (this.queue.length > 0 && this.active < this.maxConcurrent) {
this.active++;
const { imageName, imageTag, resolve } = this.queue.shift();

try {
const result = await this.k3.imageCore.pullAnImage(imageName, imageTag);
this.results.push({ status: 'success', imageName, imageTag, message: result });
console.log(`${result}`);
resolve({ success: true, message: result });
} catch (error) {
this.results.push({ status: 'failed', imageName, imageTag, error: error.message });
console.log(`✗ Failed to pull ${imageName}:${imageTag} - ${error.message}`);
resolve({ success: false, error: error.message });
}

this.active--;
this.processQueue();
}
}

getResults() {
return this.results;
}
}

const manager = new ImagePullManager(k3, 2);

await Promise.all([
manager.pull('alpine', 'latest'),
manager.pull('nginx', '1.25'),
manager.pull('node', '18'),
manager.pull('postgres', '15')
]);

console.log('Final results:', manager.getResults());

نکات عملی

  1. فضای دیسک:

    • حداقل 2.5 برابر اندازه ایمیج نیاز است
    • برای ایمیج‌های بزرگ (۱ GB+) خیلی زمان‌بر است
    • فضای دیسک کافی کنید قبل از pull
  2. اتصال شبکه:

    • اتصال پایدار و سریع نیاز است
    • proxy/firewall مسدود نباید کند
    • authentication اگر registry private است
  3. ایمیج موجود:

    • نمی‌توان ایمیج دوبار pull کنید
    • برای بروزرسانی، حذف کنید و دوباره pull کنید
  4. Performance:

    • Pull زمان‌بر است، برای بهتری parallel انجام دهید
    • maxConcurrent = 2-3 بهتری است
  5. Registry:

    • Docker Hub اگر نام داده نشود
    • Private registry نیاز به credentials دارد
    • نام کامل: registry.com/repo/image:tag
  6. Validation:

    • نام و تگ قبل از pull بررسی شود
    • ایمیج موجود بررسی شود (ImageAlreadyExists)
  7. Logging:

    • تمام pull‌ها توسط سیستم log می‌شود
    • برای audit، log‌ها را ذخیره کنید

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

  1. اعتبارسنجی پارامترها
  2. بررسی وجود ایمیج
  3. ایجاد دایرکتوری ایمیج اگر نیاز
  4. بررسی اطلاعات از رجیستری
  5. بررسی فضای دیسک
  6. دانلود ایمیج (skopeo)
  7. یافتن blob‌های ایمیج
  8. ایجاد رکوردهای blob در DB
  9. محاسبه اندازه ایمیج
  10. دریافت تاریخچه ایمیج
  11. ایجاد رکورد ایمیج در DB
  12. Logging موفقیت

مرجع سریع

وضعیتکدتوضیح
موفق200ایمیج دانلود شد
پارامتر نامعتبر422InvalidImageNameOrTag
ایمیج موجود409ImageAlreadyExists
فضای کم507InsufficientDiskSpace
ایمیج یافت نشد500ImagePullFailure
خطای رجیستری500RegistryInspectFailure
خطای DB500CreateImageRecordFailure
خطای عمومی500GenericFailure

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

Application Deployment

const result = await pullAnImage('myapp', 'v1.0');

Multi-Image Setup

const images = ['alpine', 'nginx', 'node'];
for (const img of images) {
await pullAnImage(img, 'latest');
}

CI/CD Pipeline

await pullAnImage('builder', buildVersion);

Development Environment

const result = await pullAnImage('postgres', '15');

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