خطای 403 هنگام docker pull روی سرور ایران، نتیجه تحریم داکر است: Docker Hub درخواست IP ایران را رد می‌کند و ایمیج دانلود نمی‌شود. راه پایدار، معرفی یک میرور داخلی Docker Hub در فایل /etc/docker/daemon.json، سنجیدن ایمیج با digest رسمی و نگه‌داشتن نسخه آفلاین ایمیج‌های حیاتی است.

نشانه روی سرورعلتراه‌حل کوتاه
پیام pull access denied همراه با 403 Forbiddenمسدود بودن IP ایران در Docker Hubتنظیم registry-mirrors در daemon.json
پیام toomanyrequests با کد 429تمام شدن سهمیه pull در بازه ۶ ساعتهصبر، ورود به حساب یا رجیستری خصوصی داخلی
ایمیج ghcr.io یا quay.io دانلود نمی‌شودمیرور فقط ایمیج‌های Docker Hub را پوشش می‌دهدتست دسترسی با curl و انتقال فایل tar
نیاز به استقرار در زمان قطعیوابستگی به رجیستری بیرونینسخه آفلاین با docker save

💡 نکته کلیدی

میرور رجیستری سروری است که ایمیج‌های Docker Hub را از طرف شما دریافت و تحویل می‌دهد.
✅ راه سریع: کلید registry-mirrors را در daemon.json اضافه و سرویس را با systemctl reload docker بارگذاری کنید (بخش دوم).
✅ این مسدودی به ارائه‌دهنده ربطی ندارد و روی هر VPS ایران با IP داخلی دیده می‌شود؛ برای ghcr.io و quay.io هم راه جداگانه لازم است.

بیشتر راهنماهای فارسی به یک آدرس میرور ختم می‌شوند؛ اما وقتی میرور یک روز از دسترس خارج شود یا ایمیج مشکوکی تحویل دهد، صاحب سرور نمی‌داند ایراد از کجاست. ترتیب این راهنما همان ترتیب کار روی سرور است: اول نوع خطا را با یک دستور تشخیص می‌دهید، بعد میرور را تنظیم و بدون خاموش کردن کانتینرها اعمال می‌کنید. سپس اصالت ایمیج را می‌سنجید و آخر سر برای روز قطعی، نسخه پشتیبان محلی می‌سازید.

تحریم داکر هاب؛ رفع خطای 403 و دانلود ایمیج روی سرور ایران

علت خطای 403 و toomanyrequests در تحریم داکر چیست؟

خطای 403 یعنی Docker Hub به دلیل مقررات صادراتی آمریکا، درخواست را بر اساس موقعیت IP رد کرده است. پیام toomanyrequests با کد 429 موضوع دیگری است: سهمیه pull در بازه ۶ ساعته تمام شده است. اولی با میرور حل می‌شود و دومی با مدیریت سهمیه.

صفحه‌ای که Docker Hub برای IPهای مسدود برمی‌گرداند، طبق متنی که یکی از کاربران در انجمن Docker نقل کرده، می‌گوید Docker شرکتی آمریکایی است و باید از مقررات کنترل صادرات پیروی کند. ایران هم در فهرست مناطق مسدود آمده است. فایل NOTICE پروژه Moby هم صریحاً می‌گوید استفاده و انتقال Docker ممکن است تابع محدودیت‌های دولت آمریکا باشد.

روی سرور، این مسدودی معمولاً با پیامی شبیه خطای «نام اشتباه ایمیج» ظاهر می‌شود. نشانه اصلی، عبارت 403 Forbidden در انتهای پیام است:

Error response from daemon: pull access denied for nginx, repository does not exist or may require 'docker login'
... denied: <html><body><h1>403 Forbidden</h1> ...

تشخیص نوع خطا با یک دستور curl

پیش از هر تغییری، مستقیم از خود رجیستری بپرسید چه جوابی می‌دهد. طبق مشخصات OCI Distribution، نقطه پایانی /v2/ در حالت موفق 200 برمی‌گرداند و اگر رجیستری احراز هویت بخواهد 401. از IP خارج از ایران، هر سه رجیستری زیر پاسخ 401 می‌دهند.

curl -s -o /dev/null --max-time 10 -w "%{http_code}\n" https://registry-1.docker.io/v2/
curl -s -o /dev/null --max-time 10 -w "%{http_code}\n" https://ghcr.io/v2/
curl -s -o /dev/null --max-time 10 -w "%{http_code}\n" https://quay.io/v2/
خروجی دستورمعنااقدام بعدی
پاسخ 200رجیستری باز است و احراز هویت نمی‌خواهدمعمولاً رجیستری داخلی خودتان؛ pull را امتحان کنید
پاسخ 401سرور API در دسترس است و توکن می‌خواهدبا یک docker pull واقعی تأیید کنید؛ توکن و لایه‌ها از میزبان‌های دیگری می‌آیند
پاسخ 403نشانی IP سرور در فهرست مسدود استتنظیم میرور برای Docker Hub یا انتقال فایل tar
پاسخ 429سهمیه pull تمام شده استصبر تا پایان بازه ۶ ساعته یا کش داخلی
کد 000پاسخی نیامد؛ مسیر شبکه یا DNS قطع استبررسی resolv.conf و دسترسی بین‌الملل سرور

فرق 403 با toomanyrequests در عمل

طبق مستندات سهمیه Docker Hub (به‌روزرسانی سپتامبر 2026)، کاربر بدون ورود ۱۰۰ pull در هر ۶ ساعت به ازای هر IPv4 یا هر زیرشبکه IPv6 با پیشوند /64 دارد. سقف حساب Personal هم ۲۰۰ pull است. پس از عبور از سقف، Docker Hub پاسخ 429 همراه با متن «You have reached your pull rate limit» برمی‌گرداند.

روی سرور ایران معمولاً اول 403 دیده می‌شود، چون درخواست اصلاً به مرحله شمارش نمی‌رسد. اگر بعد از تنظیم میرور پیام 429 ظاهر شد، احتمالاً سهمیه خود میرور پر شده است؛ صفحه میرور در مستندات Docker تأکید می‌کند که میرورهای Docker Hub هم تابع سیاست استفاده منصفانه هستند. در این حالت کش داخلی، که در بخش سوم می‌آید، تعداد درخواست‌ها را کم می‌کند.

Blocked Docker Registry Access 1 تحریم داکر هاب؛ رفع خطای 403 و دانلود ایمیج روی سرور ایران

تنظیم registry-mirrors در فایل daemon.json

برای رفع خطا در سطح سرور، آدرس میرور را در کلید registry-mirrors فایل /etc/docker/daemon.json بنویسید، فایل را با dockerd --validate بررسی کنید و سرویس را reload کنید. از آن به بعد هر docker pull برای ایمیج‌های Docker Hub اول سراغ میرور می‌رود.

ساخت یا ویرایش فایل daemon.json

مسیر پیش‌فرض این فایل در لینوکس، طبق مرجع dockerd، همان /etc/docker/daemon.json است. اگر فایل از قبل وجود دارد (مثلاً برای log-driver یا data-root)، آن را بازنویسی نکنید؛ کلید جدید را با jq ادغام کنید. اگر فایل وجود ندارد، حالت دوم را اجرا کنید.

# هشدار: tee فایل موجود را کامل بازنویسی می‌کند و تنظیمات قبلی (مثل data-root) از دست می‌رود
test -f /etc/docker/daemon.json && echo "exists: merge" || echo "missing: create"

# حالت ۱: فایل وجود دارد؛ ادغام با jq (نصب: sudo apt install jq)
sudo cp -a /etc/docker/daemon.json /etc/docker/daemon.json.bak
sudo jq '. + {"registry-mirrors": ["https://registry.docker.ir"]}' /etc/docker/daemon.json.bak | sudo tee /etc/docker/daemon.json > /dev/null

# حالت ۲: فایل وجود ندارد
sudo mkdir -p /etc/docker
echo '{"registry-mirrors": ["https://registry.docker.ir"]}' | sudo tee /etc/docker/daemon.json > /dev/null

آدرس https://registry.docker.ir نمونه‌ای است که سایت docker.ir برای عبور از تحریم داکر منتشر کرده است. این سایت نام گرداننده میرور را اعلام نکرده و صفحه قوانین فعالی ندارد. پس پیش از استفاده در محیط اصلی، digest ایمیج‌ها را طبق بخش سوم راستی‌آزمایی کنید. docker.ir برای اعمال تنظیم، ری‌استارت سرویس را پیشنهاد می‌دهد، اما همان‌طور که پایین‌تر می‌آید reload کافی است.

اعمال تغییر بدون خاموش کردن کانتینرها

بسیاری از راهنماها دستور systemctl restart docker را پیشنهاد می‌کنند. طبق مستندات live-restore، توقف daemon به‌طور پیش‌فرض کانتینرهای در حال اجرا را خاموش می‌کند؛ کانتینرهای دارای restart policy بعداً بالا می‌آیند، اما وقفه پیش می‌آید. جدول «Configuration reload behavior» در مرجع dockerd گزینه registry-mirrors را جزو تنظیماتی آورده که با سیگنال SIGHUP و بدون ری‌استارت پروسه بارگذاری می‌شوند. فایل سرویس systemd پروژه Moby هم برای reload همین سیگنال را می‌فرستد.

sudo dockerd --validate --config-file /etc/docker/daemon.json
sudo systemctl reload docker
docker info | grep -A2 "Registry Mirrors"

خروجی سالم دستور اول configuration OK است و دستور آخر باید آدرس میرور را زیر عنوان Registry Mirrors نشان دهد. اگر dockerd با فلگ --registry-mirror اجرا شده باشد، reload به دلیل تعارض اعمال نمی‌شود ولی سرویس هم متوقف نمی‌شود؛ پس خروجی docker info را حتماً ببینید. اگر خطای JSON گرفتید، علامت " یا کامای جاافتاده رایج‌ترین علت است؛ با فایل .bak برگردید و دوباره ادغام کنید.

فراخوانی مستقیم ایمیج از میرور

گاهی دسترسی root برای ویرایش daemon.json ندارید یا می‌خواهید فقط یک ایمیج را امتحان کنید. در این حالت نام میرور را جلوی ایمیج بنویسید و بعد آن را با نام استاندارد تگ کنید تا فایل‌های compose بدون تغییر کار کنند. ایمیج‌های رسمی Docker Hub در مسیر library/ قرار دارند.

docker pull registry.docker.ir/library/nginx:alpine
docker tag registry.docker.ir/library/nginx:alpine nginx:alpine

⚠️ محدودیت مهم

طبق صفحه Mirror the Docker Hub library، فعلاً فقط Docker Hub مرکزی را می‌شود میرور کرد و رجیستری خصوصی دیگری قابل میرور نیست. پس تنظیم بالا هیچ اثری روی ایمیج‌هایی مثل ghcr.io/... یا quay.io/... ندارد.

تنظیم registry-mirrors در فایل daemon.json

امنیت میرورهای داخلی و دریافت ایمیج از GHCR و Quay

میرورهای داخلی رایج‌ترین پاسخ به تحریم داکر هستند، اما هر میرور واسطه‌ای است که می‌تواند محتوای دیگری تحویل دهد. پس اصالت ایمیج را با digest رسمی راستی‌آزمایی کنید و ایمیج‌های GHCR و Quay را جداگانه بیازمایید؛ بیشتر آموزش‌ها این مرحله را ندارند، در حالی که خطر اصلی همین‌جاست.

راستی‌آزمایی digest ایمیج با مخزن repo-info

هر ایمیج یک digest از نوع sha256 دارد که از محتوای آن ساخته می‌شود؛ اگر حتی یک بایت عوض شود، digest هم عوض می‌شود. مخزن docker-library/repo-info در GitHub برای هر تگ رسمی، فایلی با دستور pull بر اساس digest نگه می‌دارد؛ مثلاً فایل repos/nginx/remote/alpine.md. GitHub هم طبق اعلامیه رسمی ژانویه 2021 با مجوز دولت آمریکا برای توسعه‌دهندگان ایرانی باز است.

docker image inspect --format '{{json .RepoDigests}}' nginx:alpine
# digest را با خط docker pull nginx@sha256:... در فایل زیر مقایسه کنید:
# https://github.com/docker-library/repo-info/blob/master/repos/nginx/remote/alpine.md

اگر ایمیج را با نام میرور گرفته باشید، RepoDigests همان digest را با پیشوند registry.docker.ir/library/nginx نشان می‌دهد و فقط بخش sha256 مهم است. تگ‌ها با هر انتشار تازه به digest جدیدی اشاره می‌کنند، پس عدم تطابق همیشه به معنی دستکاری نیست. راه قطعی این است که در فایل compose به‌جای تگ، خود digest را بنویسید. در این حالت Docker محتوای دریافتی از میرور را با همان hash مقایسه می‌کند و ایمیج تغییرکرده را نمی‌پذیرد.

docker pull nginx@sha256:<digest-from-repo-info>

# در compose.yaml:
#   services:
#     web:
#       image: nginx@sha256:<digest-from-repo-info>

ایمیج‌های GHCR و Quay

ایمیج‌های ghcr.io و quay.io از مسیر میرور Docker Hub عبور نمی‌کنند. اول با همان دستور curl بخش اول وضعیت هر رجیستری را از روی سرور خودتان بررسی کنید. پاسخ 401 فقط یعنی API در دسترس است؛ نتیجه نهایی را با یک docker pull واقعی بگیرید. اگر 403 آمد یا pull شکست خورد، ایمیج را روی سیستمی بیرون از ایران (مثلاً runner یک سرویس CI) بگیرید، با docker save آرشیو کنید و با scp به سرور بفرستید.

رجیستری و کش داخلی برای چند سرور

وقتی چند سرور دارید، بهتر است هر ایمیج یک بار دریافت شود و بقیه سرورها از نسخه داخلی بخوانند. ایمیج رسمی registry:3 طبق مستندات پروژه Distribution با یک دستور بالا می‌آید. در مثال زیر پورت فقط روی 127.0.0.1 باز است و ایمیج‌های GHCR یا Quay را پس از انتقال با tag و push در آن نگه می‌دارید.

docker run -d -p 127.0.0.1:5000:5000 --restart=always --name registry registry:3
docker tag ghcr.io/OWNER/APP:1.0 localhost:5000/app:1.0
docker push localhost:5000/app:1.0

برای ایمیج‌های Docker Hub، همین ایمیج را می‌شود در حالت pull-through cache اجرا کرد. مستندات Distribution کلید proxy.remoteurl را با Docker Hub مثال می‌زنند، ولی مقدار آن قابل تنظیم است؛ اگر upstream را میرور داخلی بگذارید، 403 پیش نمی‌آید. پیش از تکیه بر این کش، با یک pull آزمایشی آن را بیازمایید.

docker run -d -p 127.0.0.1:5001:5000 --restart=always --name hub-cache \
  -e REGISTRY_PROXY_REMOTEURL=https://registry.docker.ir registry:3

⚠️ هشدار امنیتی رجیستری

مستندات Distribution می‌گویند این پیکربندی‌های اولیه فقط برای آزمایش مناسب‌اند و رجیستری تولیدی باید با TLS محافظت شود و بهتر است کنترل دسترسی داشته باشد. طبق مستندات شبکه Docker، پورت منتشرشده قوانین ufw را دور می‌زند؛ پس رجیستری بدون احراز هویت را هرگز روی 0.0.0.0 باز نگذارید. برای سرورهای دیگر، آن را پشت TLS و احراز هویت روی شبکه خصوصی بگذارید و آدرسش را در registry-mirrors آن سرورها بنویسید. کلید insecure-registries فقط برای آزمایش در شبکه خصوصی است.

🔶 نکته درباره سرور مجازی ایران وب‌داده

هر سرور مجازی ایران وب‌داده IP مستقیم دارد که از اینترنت بین‌الملل هم در دسترس است. پس رجیستری یا کشی که روی آن راه می‌اندازید باید به 127.0.0.1 یا شبکه خصوصی محدود باشد، یا TLS و احراز هویت داشته باشد.

امنیت میرورهای داخلی و دریافت ایمیج از GHCR و Quay

نگهداری آفلاین ایمیج‌ها و چک‌لیست استقرار کانتینر

ایمیج‌های حیاتی را با docker save به فایل tar تبدیل کنید و روی دیسک یا سرور دیگری نگه دارید تا اگر میرور یا اینترنت بین‌الملل قطع شد، تحریم داکر استقرار شما را متوقف نکند. این روش به هیچ سرویس بیرونی وابسته نیست و با docker load برمی‌گردد.

ساخت و بازگردانی نسخه آفلاین

طبق مرجع docker image save، خروجی این دستور یک آرشیو tar است و می‌شود آن را برای کم کردن حجم از gzip عبور داد. در یک فایل می‌توانید چند ایمیج را با هم ذخیره کنید؛ docker load هم فایل فشرده با gzip را مستقیم می‌خواند.

docker save nginx:alpine postgres:16 | gzip > stack-images.tar.gz
scp stack-images.tar.gz user@backup-host:/srv/images/
docker load -i stack-images.tar.gz

گزینه --platform فقط یک معماری را ذخیره می‌کند (مثلاً linux/amd64) و حجم آرشیو را کم می‌کند. این گزینه به API نسخه 1.48 یا بالاتر نیاز دارد.

docker save --platform linux/amd64 -o nginx-amd64.tar nginx:alpine

چک‌لیست استقرار روی سرور داخلی

  1. پاسخ رجیستری‌های موردنیاز را با curl بگیرید و با یک pull واقعی تأیید کنید.
  2. یک میرور Docker Hub را از صفحه گرداننده‌اش در daemon.json ادغام کنید و برای چند سرور کش داخلی بسازید.
  3. فایل را با dockerd --validate بررسی کنید و سرویس را reload کنید، نه restart.
  4. در فایل compose ایمیج‌های حساس را با digest بنویسید، نه با تگ latest.
  5. ایمیج‌های خارج از Docker Hub را از قبل در رجیستری داخلی push کنید.
  6. رجیستری و کش داخلی را به 127.0.0.1 یا شبکه خصوصی محدود کنید یا TLS و احراز هویت بگذارید.
  7. از ایمیج‌های حیاتی بعد از هر به‌روزرسانی، آرشیو docker save بگیرید.
  8. دست‌کم یک بار بازگردانی را روی سرور آزمایشی تمرین کنید.

اگر خود Docker Engine هنوز نصب نشده است، مراحل نصب را در آموزش نصب Docker روی اوبونتو 24.04 ببینید؛ آن راهنما به نصب می‌پردازد و این مقاله به دریافت ایمیج بعد از نصب. برای انتخاب توزیع مناسب، راهنمای خرید سرور مجازی لینوکس معیارهای منابع و سیستم‌عامل را مرور می‌کند.

نگهداری آفلاین ایمیج‌ها و چک‌لیست استقرار کانتینر

اجرای این چک‌لیست روی سرور مجازی ایران وب‌داده

در پنل سرور مجازی ایران وب‌داده، پیش از تغییر daemon.json می‌توانید اسنپ‌شات بگیرید و اگر سرویس Docker بالا نیامد، همان حالت قبل را بازگردانید. اگر SSH هم قطع شد، کنسول VNC و حالت Rescue راه دسترسی به فایل را باز نگه می‌دارند. برای تمرین بازگردانی آرشیوها هم امکان تست ساعتی رایگان سرور وجود دارد.

پرسش‌های رایج درباره دریافت ایمیج Docker در ایران:

چرا docker pull روی سرور ایران خطای 403 می‌دهد؟

سرویس Docker Hub برای پیروی از مقررات کنترل صادرات آمریکا، درخواست IPهای ایران را رد می‌کند. این خطا به نسخه Docker یا تنظیمات سیستم‌عامل ربطی ندارد و با تنظیم میرور در daemon.json برطرف می‌شود.

تغییر DNS معمولی کمکی نمی‌کند، چون مسدودسازی بر اساس IP مبدأ درخواست است، نه نام دامنه. راه پایدار، میرور داخلی و آرشیو محلی ایمیج‌هاست.

میرورهای Docker Hub هم تابع سیاست استفاده منصفانه Docker هستند و ممکن است سهمیه‌شان پر شود. ایمیج‌های پرتکرار را در کش یا رجیستری داخلی نگه دارید و در CI به‌جای pull مکرر از نسخه محلی استفاده کنید.

خیر. طبق مستندات Docker، کلید registry-mirrors فقط برای Docker Hub است. دسترسی این رجیستری‌ها را با curl روی مسیر /v2/ بررسی کنید؛ پاسخ 401 یعنی API در دسترس است و باید با یک pull واقعی تأیید شود. پاسخ 403 یعنی باید ایمیج را به شکل فایل tar منتقل کنید.

دستور docker info را اجرا کنید؛ آدرس میرور باید زیر عنوان Registry Mirrors دیده شود. اگر نیست، فایل daemon.json را با dockerd –validate بررسی کنید و سرویس را reload کنید.

میرور واسطه است و در اصل می‌تواند محتوای تغییرکرده تحویل دهد. digest ایمیج را با فایل همان تگ در مخزن docker-library/repo-info مقایسه کنید و برای سرویس‌های حساس، ایمیج را در compose با digest بنویسید تا Docker محتوای دیگر را نپذیرد.

روی سیستمی که به رجیستری دسترسی دارد، با docker save آرشیو بسازید و با scp یا rsync به سرور بفرستید. روی سرور مقصد docker load -i را اجرا کنید؛ این دستور فایل فشرده با gzip را هم می‌خواند.

جمع‌بندی؛ تحریم داکر در سه لایه مشکل دریافت ایمیج روی سرور ایران از IP سرور شروع می‌شود، نه از تنظیمات شما؛ پس راه‌حل هم باید مستقل از Docker Hub باشد. لایه اول، ادغام میرور در daemon.json است که با reload و بدون توقف کانتینرها اعمال می‌شود و با docker info قابل بررسی است. لایه دوم، راستی‌آزمایی ایمیج است: digest را با مخزن repo-info مقایسه کنید و ایمیج‌های حساس را با digest بنویسید. برای چند سرور هم یک کش یا رجیستری داخلی بسازید و آن را به شبکه خصوصی محدود کنید. لایه سوم، آرشیو محلی با docker save است که در قطعی میرور یا اینترنت بین‌الملل، استقرار را ممکن نگه می‌دارد. ایمیج‌های GHCR و Quay را هم فراموش نکنید؛ میرور Docker Hub روی آن‌ها اثری ندارد و باید جداگانه آزموده شوند. قدم اول: دستور curl بخش اول را روی سرور اجرا کنید؛ راه‌حل مناسب از جواب آن معلوم می‌شود.

🚀 مشاهده پلن‌ها و تست ساعتی رایگان

سرور مجازی ایران وب‌داده در دیتاسنتر تهران میزبانی می‌شود، با پنل اسنپ‌شات و کنسول VNC مدیریت می‌شود و امکان تست ساعتی رایگان دارد.

اگر میرور دیگری را آزموده‌اید یا با خطایی روبه‌رو شدید که اینجا نیامده، در بخش نظرات بنویسید تا راهنما را کامل‌تر کنیم.

منابع

وب داده
وب داده

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

مقاله‌ها: 228
پاسخی بگذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *