اگر 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 و PyPI راهاندازی کردهاند. آدرس دقیق را همیشه از صفحهٔ مستندات رسمی همان سرویسدهنده بردارید، چون آدرسها گاهی تغییر میکنند.
پیش از انتخاب، به این نکات دقت کنید:
- HTTPS داشته باشد: هرگز از میرور HTTP بدون رمزنگاری استفاده نکنید.
- بهروز باشد: نسخهٔ جدید یک پکیج شناختهشده را جستوجو کنید و ببینید در میرور هم موجود است.
- یکپارچگی بستهها حفظ شود: npm با فایل
package-lock.jsonو فیلدintegrityو pip با گزینهٔ--require-hashesمیتوانند بررسی کنند که فایل دریافتی با نسخهٔ اصلی یکی است. - از منبع قابل اعتماد باشد: میرور ناشناس میتواند پکیج دستکاریشده تحویل دهد.
در مثالهای این مقاله آدرسهای فرضی 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 روی همین سرور بازسازی کنید.
$ 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'$
تنظیم میرور برای 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 را چطور حل کنم؟
این پکیجها فایل باینری را جدا از رجیستری دانلود میکنند. در مستندات هر پکیج متغیر محیطی برای تعیین آدرس دانلود یا رد کردن آن وجود دارد؛ یا بستهٔ آماده را روی سرور دیگری بسازید و منتقل کنید.
از ۱٬۲۰۰ تومان در ساعت · پرداخت ریالی



