آموزش سرور

تنظیم میرور npm و pip روی سرور ایران و رفع خطای نصب پکیج‌ها

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

ERRnpmpipآموزش سرورتنظیم میرور npm و pipروی سرور ایران و رفعخطای نصب پکیج‌هامجلهٔ کلودیفایclodify.net/blog
پاسخ کوتاه

اگر npm install یا pip install روی سرور ایران با خطای 403، Timeout یا ECONNRESET متوقف می‌شود، معمولاً مسیر سرور تا رجیستری رسمی مشکل دارد. راه‌حل، تنظیم یک میرور (آینهٔ) معتبر است: در npm با دستور npm config set registry و در pip با pip config set global.index-url. این تنظیم را می‌توانید برای کل سیستم، یک پروژه یا داخل Dockerfile انجام دهید و هر زمان خواستید به رجیستری رسمی برگردید.

چرا نصب پکیج روی سرور ایران خطا می‌دهد؟

مدیران بستهٔ زبان‌های برنامه‌نویسی، پکیج‌ها را از یک رجیستری مرکزی دانلود می‌کنند: npm از registry.npmjs.org و pip از pypi.org و files.pythonhosted.org. روی سرورهای داخل ایران، دسترسی به این مقصدها گاهی کند، ناپایدار یا به دلیل محدودیت‌های اعمال‌شده از سمت خود سرویس‌دهنده‌ها با خطا همراه است. نتیجه، خطاهایی از این دست است:

  • در npm: ETIMEDOUT، ECONNRESET، 403 Forbidden یا گیر کردن طولانی روی مرحلهٔ idealTree.
  • در pip: Read timed out، Connection reset by peer، Could not find a version that satisfies the requirement (وقتی اصلاً فهرست نسخه‌ها دریافت نشده است).

این مشکل شبیه همان چیزی است که برای apt و Docker Hub پیش می‌آید و راه‌حل آن را در مقالهٔ رفع خطای 403 در apt و داکر روی سرور ایران توضیح داده‌ایم. منطق کار یکی است: به‌جای مقصد اصلی، از یک میرور استفاده می‌کنیم.

نصب پکیج با میرور
درخواست پکیجهم‌گام‌سازیسرور ایرانnpm یا pipمیرور داخلیکش پکیج‌هارجیستری رسمیnpmjs یا PyPIدرخواست پکیجهم‌گام‌سازیسرور ایرانnpm یا pipمیرور داخلیکش پکیج‌هارجیستری رسمیnpmjs یا PyPI
شکل ۱ سرور به‌جای رجیستری رسمی از میرور دانلود می‌کند و میرور خودش با منبع اصلی هم‌گام است.

میرور چیست و چطور یک میرور معتبر انتخاب کنیم؟

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

پیش از انتخاب، به این نکات دقت کنید:

  1. HTTPS داشته باشد: هرگز از میرور HTTP بدون رمزنگاری استفاده نکنید.
  2. به‌روز باشد: نسخهٔ جدید یک پکیج شناخته‌شده را جست‌وجو کنید و ببینید در میرور هم موجود است.
  3. یکپارچگی بسته‌ها حفظ شود: npm با فایل package-lock.json و فیلد integrity و pip با گزینهٔ --require-hashes می‌توانند بررسی کنند که فایل دریافتی با نسخهٔ اصلی یکی است.
  4. از منبع قابل اعتماد باشد: میرور ناشناس می‌تواند پکیج دستکاری‌شده تحویل دهد.

در مثال‌های این مقاله آدرس‌های فرضی https://npm.mirror.example.ir/ و https://pypi.mirror.example.ir/simple را به کار برده‌ایم؛ آن‌ها را با آدرس میرور واقعی‌ای که انتخاب می‌کنید جایگزین کنید.

تنظیم میرور برای npm، yarn و pnpm

تنظیم سراسری برای کاربر

npm config set registry https://npm.mirror.example.ir/
npm config get registry
npm ping

دستور npm ping بررسی می‌کند که رجیستری جدید پاسخ می‌دهد. این تنظیم در فایل ~/.npmrc ذخیره می‌شود.

تنظیم فقط برای یک پروژه

یک فایل .npmrc در ریشهٔ پروژه بسازید:

echo "registry=https://npm.mirror.example.ir/" > .npmrc

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

yarn و pnpm

yarn config set registry https://npm.mirror.example.ir/        # yarn 1
yarn config set npmRegistryServer https://npm.mirror.example.ir/  # yarn 2+
pnpm config set registry https://npm.mirror.example.ir/

یک نکتهٔ مهم: اگر فایل package-lock.json یا yarn.lock قبلاً با رجیستری رسمی ساخته شده باشد، آدرس کامل فایل‌ها در آن ثبت شده است. npm نسخه‌های جدید معمولاً آدرس را با رجیستری تنظیم‌شده جایگزین می‌کند، اما اگر باز هم به آدرس رسمی درخواست رفت، فایل lock را با دستور npm install روی همین سرور بازسازی کنید.

root@server: ~
$ npm config set registry https://npm.mirror.example.ir/$ npm config get registryhttps://npm.mirror.example.ir/$ pip config set global.index-url https://pypi.mirror.example.ir/simpleWriting to /root/.config/pip/pip.conf$ pip config listglobal.index-url='https://pypi.mirror.example.ir/simple'$ 
شکل ۲ تنظیم میرور برای npm و pip و بررسی مقدار ذخیره‌شده؛ آدرس فرضی را با میرور واقعی جایگزین کنید.

تنظیم میرور برای pip

با دستور pip config

pip config set global.index-url https://pypi.mirror.example.ir/simple
pip config set global.trusted-host pypi.mirror.example.ir
pip config list

خط trusted-host فقط وقتی لازم است که گواهی میرور با مشکل روبه‌رو باشد؛ اگر میرور HTTPS معتبر دارد، آن را حذف کنید. تنظیمات در فایل ~/.config/pip/pip.conf یا /etc/pip.conf (برای کل سیستم) ذخیره می‌شود.

فقط برای یک دستور

pip install -i https://pypi.mirror.example.ir/simple requests

محیط مجازی و requirements

در محیط مجازی (venv) همان تنظیم سراسری کاربر اعمال می‌شود. اگر می‌خواهید آدرس میرور همراه پروژه باشد، خط زیر را بالای فایل requirements.txt بنویسید:

--index-url https://pypi.mirror.example.ir/simple

برای ابزارهای جدیدتر مثل uv و Poetry هم گزینهٔ مشابهی وجود دارد؛ مثلاً در uv متغیر محیطی UV_INDEX_URL همین کار را انجام می‌دهد.

تنظیم میرور داخل Dockerfile

وقتی ایمیج را روی سرور ایران می‌سازید، دستور RUN npm install یا RUN pip install داخل کانتینر اجرا می‌شود و تنظیمات سیستم میزبان را نمی‌بیند. پس باید میرور را داخل Dockerfile مشخص کنید. بهتر است آن را به‌صورت آرگومان ساخت تعریف کنید تا روی سرورهای دیگر قابل تغییر باشد:

ARG NPM_REGISTRY=https://registry.npmjs.org/
RUN npm config set registry $NPM_REGISTRY && npm ci

ARG PIP_INDEX=https://pypi.org/simple
RUN pip install --index-url $PIP_INDEX -r requirements.txt

و هنگام ساخت روی سرور ایران:

docker build --build-arg NPM_REGISTRY=https://npm.mirror.example.ir/ --build-arg PIP_INDEX=https://pypi.mirror.example.ir/simple -t myapp .

اگر خود ایمیج پایه (مثلاً node یا python) هم دانلود نمی‌شود، باید میرور Docker Hub را تنظیم کنید؛ آموزش آن در نصب داکر روی اوبونتو ۲۴.۰۴ آمده است. اصول ساخت ایمیج را هم در راهنمای Docker Compose ببینید.

وقتی میرور هم جواب نمی‌دهد

اگر با وجود میرور هنوز خطا می‌گیرید، این موارد را بررسی کنید:

  • DNS: با دستور getent hosts npm.mirror.example.ir ببینید نام دامنه به آی‌پی تبدیل می‌شود یا نه. اگر نه، مقالهٔ خطای DNS در لینوکس را ببینید.
  • پروکسی تنظیم‌شده: گاهی متغیرهای HTTP_PROXY یا HTTPS_PROXY از قبل تنظیم شده‌اند و درخواست‌ها را منحرف می‌کنند. با env | grep -i proxy بررسی کنید.
  • کش خراب: npm cache clean --force یا pip cache purge را اجرا کنید.
  • پکیج‌های بومی (Native): بعضی پکیج‌ها هنگام نصب فایل باینری از GitHub یا سایت دیگری دانلود می‌کنند (مثل sharp یا puppeteer). این درخواست‌ها از میرور npm عبور نمی‌کنند و ممکن است جداگانه خطا بدهند. معمولاً متغیر محیطی مخصوص خود پکیج برای تعیین آدرس دانلود وجود دارد.

راه‌حل جایگزین: ساخت روی سرور خارج

برای پروژه‌های بزرگ، روش تمیزتر این است که ایمیج یا بستهٔ نهایی را در جایی بسازید که به رجیستری‌های رسمی دسترسی کامل دارد و فقط خروجی آماده را به سرور ایران منتقل کنید. می‌توانید یک سرور خارج ساعتی را فقط برای مرحلهٔ ساخت روشن کنید و پس از پایان کار حذفش کنید. انتقال ایمیج با docker save و docker load یا انتقال پوشهٔ node_modules فشرده و فایل‌های wheel پایتون با scp و sftp انجام می‌شود.

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

بازگشت به تنظیمات پیش‌فرض

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

npm config delete registry
pip config unset global.index-url
pip config unset global.trusted-host

پس از این دستورها، npm و pip دوباره از رجیستری‌های رسمی استفاده می‌کنند.

نکته‌هایی برای تیم‌ها و سرورهای CI

اگر چند سرور یا چند توسعه‌دهنده دارید، تنظیم دستی میرور روی هر سیستم به‌سرعت باعث ناهماهنگی می‌شود؛ یک سرور با میرور کار می‌کند و دیگری نه، و پیدا کردن علت خطا وقت زیادی می‌گیرد. بهتر است تنظیمات را در کد پروژه نگه دارید: فایل .npmrc برای npm، خط اول requirements.txt برای pip و آرگومان‌های ساخت در Dockerfile.

در سرورهای CI مثل GitLab Runner یا GitHub Actions خودمیزبان، متغیرهای محیطی ساده‌ترین روش هستند. npm متغیر NPM_CONFIG_REGISTRY و pip متغیر PIP_INDEX_URL را می‌خوانند؛ کافی است این دو را در تنظیمات Runner روی سرور ایران تعریف کنید و روی سرور خارج تعریف نکنید.

یک راه دیگر برای تیم‌های بزرگ، راه‌اندازی یک کش داخلی مثل Verdaccio برای npm یا devpi برای pip است. این ابزارها یک بار پکیج را دریافت و برای دفعات بعد کش می‌کنند؛ هم سرعت نصب بالا می‌رود و هم وابستگی به در دسترس بودن منبع بیرونی کم می‌شود.

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

آیا استفاده از میرور امنیت پکیج‌ها را کم می‌کند؟

اگر میرور معتبر و HTTPS باشد و فایل lock پروژه را نگه دارید، npm و pip صحت فایل‌ها را با هش بررسی می‌کنند. از میرورهای ناشناس یا بدون HTTPS استفاده نکنید.

چرا npm با وجود تنظیم میرور هنوز به registry.npmjs.org درخواست می‌دهد؟

احتمالاً آدرس رسمی در فایل package-lock.json یا تنظیمات scope خاصی مثل @company:registry ثبت شده است. فایل lock را روی همین سرور بازسازی کنید و فایل‌های .npmrc پروژه و کاربر را بررسی کنید.

میرور را برای کل سیستم تنظیم کنم یا برای هر پروژه؟

اگر روی سرور فقط پروژه‌های شما اجرا می‌شود، تنظیم سراسری کاربر ساده‌تر است. اگر پروژه روی سرورهای مختلف اجرا می‌شود، تنظیم در فایل .npmrc یا آرگومان ساخت Dockerfile انعطاف بیشتری دارد.

خطای نصب پکیج‌هایی مثل sharp یا puppeteer را چطور حل کنم؟

این پکیج‌ها فایل باینری را جدا از رجیستری دانلود می‌کنند. در مستندات هر پکیج متغیر محیطی برای تعیین آدرس دانلود یا رد کردن آن وجود دارد؛ یا بستهٔ آماده را روی سرور دیگری بسازید و منتقل کنید.

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

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

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

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