آموزش سرور

انتقال ایمیج داکر بدون اینترنت با docker save و docker load

تهیه: کلودیفای (نگارش با کمک هوش مصنوعی) · انتشار: · زمان مطالعه: ۷ دقیقه

dockersaveloadآموزش سرورانتقال ایمیج داکر بدوناینترنت با docker save وdocker loadمجلهٔ کلودیفایclodify.net/blog
پاسخ کوتاه

وقتی سرور مقصد به رجیستری داکر دسترسی ندارد یا دریافت ایمیج کند و ناپایدار است، ایمیج را روی سیستمی که دسترسی دارد با docker pull بگیرید، با docker save آن را به یک فایل tar تبدیل و فشرده کنید، فایل را با scp یا rsync به سرور مقصد ببرید و آن‌جا با docker load بارگذاری کنید. به معماری پردازنده (amd64 یا arm64)، برچسب دقیق نسخه و فضای خالی دیسک دقت کنید تا ایمیج در مقصد بدون خطا اجرا شود.

چه زمانی به انتقال آفلاین ایمیج نیاز داریم؟

در حالت عادی، داکر ایمیج‌ها را مستقیم از یک رجیستری مثل Docker Hub دریافت می‌کند. اما شرایطی هست که این روش کار نمی‌کند یا به‌صرفه نیست. سرور ممکن است در شبکه‌ای ایزوله باشد که اصلاً به اینترنت دسترسی ندارد. ممکن است رجیستری برای IPهای خاصی محدودیت دسترسی یا خطای ۴۰۳ برگرداند. ممکن است اتصال بین‌المللی سرور کند یا ناپایدار باشد و دریافت ایمیج چند گیگابایتی بارها نیمه‌کاره قطع شود. یا شاید محدودیت تعداد دریافت رجیستری عمومی را رد کرده باشید.

در همهٔ این حالت‌ها، راه‌حل ساده و قابل اعتماد این است که ایمیج را جای دیگری دریافت کنید و به‌صورت یک فایل منتقل کنید. داکر برای این کار دو دستور داخلی دارد: docker save که ایمیج را با همهٔ لایه‌ها و فراداده‌هایش به یک فایل tar تبدیل می‌کند و docker load که همان فایل را در مقصد به ایمیج قابل اجرا برمی‌گرداند. اگر علت مشکل شما خطای ۴۰۳ است، پیش از این روش، راه‌حل‌های خطای ۴۰۳ داکر روی سرور ایران را هم ببینید.

مسیر انتقال آفلاین ایمیج
ذخیرهفایل فشردهبارگذاریسیستم واسطdocker pullفایل tar.gzdocker save + gzipانتقالrsync یا scpسرور مقصدdocker loadذخیرهفایل فشردهبارگذاریسیستم واسطdocker pullفایل tar.gzdocker save + gzipانتقالrsync یا scpسرور مقصدdocker load
شکل ۱ سرور مقصد هیچ‌وقت مستقیم به رجیستری وصل نمی‌شود.

گام اول: دریافت ایمیج روی سیستم واسط

سیستم واسط می‌تواند لپ‌تاپ شما، یک سرور خارج یا هر ماشینی باشد که داکر دارد و به رجیستری دسترسی دارد. نکتهٔ مهم، معماری پردازنده است. اگر سرور مقصد x86_64 است (رایج‌ترین حالت در سرورهای مجازی) و شما روی مک با تراشهٔ اپل کار می‌کنید، باید ایمیج را صریحاً برای amd64 بگیرید:

docker pull --platform linux/amd64 nginx:1.27-alpine
docker image ls nginx

همیشه از برچسب دقیق نسخه استفاده کنید، نه latest. برچسب latest در طول زمان به نسخه‌های مختلف اشاره می‌کند و اگر بعداً بخواهید همان نسخه را دوباره منتقل کنید یا مشکلی را بررسی کنید، نمی‌دانید دقیقاً چه چیزی روی سرور است. برای یادآوری دستورهای پایهٔ مدیریت ایمیج، دستورهای پایهٔ داکر را ببینید.

گام دوم: ذخیرهٔ ایمیج در فایل و فشرده‌سازی

دستور docker save خروجی را به‌صورت آرشیو tar می‌نویسد. چون لایه‌های ایمیج معمولاً قابل فشرده‌سازی‌اند، بهتر است خروجی را مستقیم با gzip یا zstd فشرده کنید تا حجم انتقال کمتر شود:

docker save nginx:1.27-alpine | gzip > nginx-1.27-alpine.tar.gz
ls -lh nginx-1.27-alpine.tar.gz

می‌توانید چند ایمیج را در یک فایل ذخیره کنید. این کار برای پروژه‌هایی که چند سرویس دارند مفید است، چون لایه‌های مشترک فقط یک بار ذخیره می‌شوند:

docker save app:1.4 postgres:16 redis:7 | gzip > stack-1.4.tar.gz

پیش از انتقال، یک چک‌سام بگیرید تا در مقصد مطمئن شوید فایل سالم رسیده است. دستور sha256sum روی هر دو سمت باید عدد یکسان نشان دهد.

ذخیره و بارگذاری ایمیج
root@server: ~
$ docker pull --platform linux/amd64 nginx:1.27-alpine$ docker save nginx:1.27-alpine | gzip > nginx-1.27-alpine.tar.gz$ rsync -avP nginx-1.27-alpine.tar.gz root@SERVER_IP:/root/images/$ docker load -i /root/images/nginx-1.27-alpine.tar.gzLoaded image: nginx:1.27-alpine$ 
شکل ۲ خط آخر روی سرور مقصد اجرا می‌شود.

گام سوم: انتقال فایل به سرور مقصد

برای انتقال، scp ساده‌ترین گزینه است. اما برای فایل‌های حجیم روی اتصال ناپایدار، rsync بهتر است، چون اگر انتقال قطع شود می‌تواند از همان نقطه ادامه دهد:

rsync -avP nginx-1.27-alpine.tar.gz user@SERVER_IP:/root/images/

گزینهٔ P هم نوار پیشرفت نشان می‌دهد و هم فایل نیمه‌کاره را نگه می‌دارد. اگر SSH روی پورت غیرپیش‌فرض است، با گزینهٔ e پورت را مشخص کنید. جزئیات کامل این ابزارها در مقالهٔ انتقال فایل با scp و sftp و برای همگام‌سازی‌های تکراری در بکاپ سرور با rsync آمده است.

اگر سرور مقصد کاملاً ایزوله است و حتی SSH از بیرون ندارد، می‌توانید فایل را روی دیسک قابل حمل یا از طریق یک سرور میانی در همان شبکهٔ داخلی منتقل کنید. منطق کار تغییر نمی‌کند: فقط یک فایل جابه‌جا می‌شود.

گام چهارم: بارگذاری ایمیج در مقصد

روی سرور مقصد، ابتدا چک‌سام را مقایسه کنید و سپس ایمیج را بارگذاری کنید. docker load فایل فشرده با gzip را مستقیم می‌خواند:

sha256sum nginx-1.27-alpine.tar.gz
docker load -i nginx-1.27-alpine.tar.gz
docker image ls

خروجی docker load نام و برچسب ایمیج بارگذاری‌شده را نشان می‌دهد. حالا می‌توانید مثل همیشه با docker run یا docker compose از آن استفاده کنید. فقط دقت کنید که در فایل compose، گزینهٔ pull_policy را طوری تنظیم کنید که داکر برای دریافت دوبارهٔ ایمیج به رجیستری مراجعه نکند؛ مقدار missing یا never برای سرورهای ایزوله مناسب است. ساختار فایل compose در راهنمای داکر کامپوز توضیح داده شده است.

تفاوت docker save با docker export

این دو دستور شبیه به نظر می‌رسند، اما کاملاً متفاوت‌اند. docker save روی ایمیج کار می‌کند و همهٔ لایه‌ها، تاریخچه، برچسب‌ها و تنظیمات اجرایی مثل CMD و ENV را حفظ می‌کند. خروجی آن در مقصد دقیقاً همان ایمیج است. اما docker export روی کانتینر کار می‌کند و فقط فایل‌سیستم فعلی آن را به‌صورت یک لایهٔ تخت خروجی می‌دهد. تاریخچه و تنظیمات اجرایی از بین می‌رود و با docker import باید دوباره مشخص شوند.

برای انتقال ایمیج‌های رسمی یا ایمیج‌هایی که خودتان ساخته‌اید، همیشه save و load را انتخاب کنید. export و import فقط وقتی کاربرد دارند که بخواهید وضعیت فعلی یک کانتینر را به‌صورت یک ایمیج تخت ذخیره کنید، که معمولاً روش توصیه‌شده‌ای نیست؛ بهتر است تغییرات را در Dockerfile ثبت کنید.

docker save در برابر docker export
docker save / load
  • روی ایمیج کار می‌کند
  • لایه‌ها و تاریخچه حفظ می‌شود
  • CMD و ENV حفظ می‌شود
  • روش توصیه‌شده برای انتقال
در برابر
docker export / import
  • روی کانتینر کار می‌کند
  • یک لایهٔ تخت
  • تنظیمات اجرایی از بین می‌رود
  • فقط برای موارد خاص
شکل ۳ برای انتقال ایمیج تقریباً همیشه save و load درست است.

خودکارسازی برای استقرارهای تکراری

اگر مرتب نسخهٔ جدید برنامه را به سرورهای ایزوله منتقل می‌کنید، یک اسکریپت کوچک بنویسید که ایمیج‌های لازم را بر اساس فایل compose بخواند، آن‌ها را ذخیره و فشرده کند، به سرور بفرستد و آن‌جا بارگذاری کند. دستور docker compose config --images فهرست ایمیج‌های یک پروژه را چاپ می‌کند و می‌تواند ورودی همین اسکریپت باشد.

برای تیم‌هایی که چند سرور داخلی دارند، راه‌اندازی یک رجیستری خصوصی داخل شبکه هم گزینهٔ خوبی است. در این مدل، ایمیج‌ها یک بار به رجیستری داخلی منتقل می‌شوند و همهٔ سرورها از آن‌جا دریافت می‌کنند. اما برای یک یا دو سرور، روش save و load ساده‌تر است و هیچ سرویس اضافه‌ای برای نگهداری ندارد.

مشکلات رایج و راه‌حل‌ها

اگر پس از load، کانتینر با خطای exec format error اجرا نشد، تقریباً همیشه معماری ایمیج با سرور یکسان نیست؛ ایمیج را با گزینهٔ platform درست دوباره بگیرید. اگر load با خطای unexpected EOF متوقف شد، فایل ناقص منتقل شده است؛ چک‌سام را مقایسه کنید و با rsync دوباره انتقال دهید. اگر با پیام no space left on device مواجه شدید، به یاد داشته باشید که هنگام load هم فایل فشرده و هم لایه‌های استخراج‌شده روی دیسک هستند؛ فایل را پس از بارگذاری پاک کنید و ایمیج‌های قدیمی را با docker image prune حذف کنید. روش‌های بیشتر آزادسازی فضا در مقالهٔ خطای پر شدن دیسک آمده است.

برای سرورهای جدید، اگر می‌خواهید بیشتر بسته‌ها و ایمیج‌ها را بدون این دردسر دریافت کنید، استفاده از آینه‌های داخلی برای مخازن هم کمک می‌کند؛ روش آن در مقالهٔ آینهٔ npm و pip برای سرور ایران آمده است.

چک‌لیست کوتاه پیش از انتقال

پیش از هر انتقال، این چند مورد را مرور کنید تا در مقصد غافلگیر نشوید. برچسب دقیق نسخه را یادداشت کرده‌اید و از latest استفاده نکرده‌اید. معماری سرور مقصد را با دستور uname -m بررسی کرده‌اید و ایمیج را برای همان معماری دریافت کرده‌اید. فضای خالی دیسک مقصد دست‌کم دو برابر حجم فایل فشرده است. چک‌سام فایل را ثبت کرده‌اید. و در نهایت، فایل compose یا دستور اجرای کانتینر را همراه فایل ایمیج منتقل کرده‌اید تا در مقصد بتوانید سرویس را دقیقاً با همان تنظیمات بالا بیاورید. همین چک‌لیست ساده بیشتر خطاهای رایج انتقال آفلاین را از بین می‌برد.

سؤالات متداول

آیا docker save ایمیج‌های چندمعماری را هم ذخیره می‌کند؟

به‌طور پیش‌فرض فقط نسخه‌ای ذخیره می‌شود که روی سیستم شما دریافت شده است. برای سرور مقصد، ایمیج را با گزینهٔ platform مناسب آن معماری دریافت کنید.

فایل خروجی را با چه ابزاری فشرده کنم؟

gzip همه‌جا در دسترس است و docker load مستقیم آن را می‌خواند. zstd سریع‌تر و فشرده‌تر است، اما باید پیش از load آن را از حالت فشرده خارج کنید.

volumeها هم با docker save منتقل می‌شوند؟

نه. docker save فقط ایمیج را منتقل می‌کند. داده‌های volume را باید جداگانه با tar یا rsync منتقل کنید.

آیا می‌توانم چند ایمیج را در یک فایل ذخیره کنم؟

بله. نام چند ایمیج را پشت سر هم به docker save بدهید. لایه‌های مشترک فقط یک بار ذخیره می‌شوند و حجم فایل کمتر می‌شود.

آماده‌اید؟ سرورتان را بسازید.

از ۱٬۲۰۰ تومان در ساعت · پرداخت ریالی

سرورتان را همین حالا بسازید.

ساعتی بپردازید. هر وقت خواستید حذف کنید.