خداحافظی با خطای 403 داکرهاب: Mirror داخلی با Harbor و Nexus برای تیم‌های ایرانی

راه‌اندازی Harbor به‌عنوان Proxy Cache داکرهاب و Nexus برای npm، PyPI و NuGet؛ Build و Deploy مستقل از تحریم و اینترنت بین‌الملل.

۵ دقیقه مطالعه

هر مهندس DevOps در ایران این پیام را دیده است:

Error response from daemon: error from registry: 403 Forbidden

Docker Hub دسترسی IPهای ایرانی را محدود کرده است. اضافه بر این، Rate Limit برای کاربران ناشناس، کندی اینترنت بین‌الملل و قطعی‌های ناگهانی هم وجود دارد. نتیجه‌اش Pipelineهایی است که بی‌دلیل شکست می‌خورند و Podهایی که در وضعیت ImagePullBackOff می‌مانند.

راه‌حل پایدار، یک لایه‌ی Mirror داخل سازمان است: Harbor برای Imageها و Nexus برای پکیج‌ها. در همه‌ی پروژه‌هایی که راه‌اندازی کرده‌ام، این دو جزو اولین زیرساخت‌ها بوده‌اند.

معماری کلی

 Developers / CI Runners / Kubernetes nodes
                  │
        ┌─────────┴─────────┐
        ▼                   ▼
     Harbor               Nexus
  (container images)  (npm, PyPI, NuGet, Maven)
        │                   │
        └───── server with stable upstream access ─────▶ Docker Hub, ghcr.io, npmjs, pypi.org …

فقط سرور Harbor و Nexus به منابع خارجی دسترسی دارند؛ مثلاً از طریق یک سرور خارج از کشور یا یک Proxy پایدار. بقیه‌ی سیستم‌ها فقط با این دو صحبت می‌کنند. هر Image یا پکیج یک‌بار از بیرون دریافت و بعد از Cache داخلی سرو می‌شود.

بخش اول: Harbor به‌عنوان Proxy Cache

۱. تعریف Registry بالادستی

در پنل Harbor:

  1. Administration → Registries → New Endpoint
  2. نوع Provider را Docker Hub انتخاب کنید و اگر حساب Docker Hub دارید، اطلاعاتش را وارد کنید تا Rate Limit بالاتری داشته باشید.
  3. همین کار را برای ghcr.io، quay.io و registry.k8s.io هم تکرار کنید (نوع Docker Registry).

۲. ساخت پروژه‌ی Proxy Cache

Projects → New Project، گزینه‌ی Proxy Cache را فعال کنید و Endpoint مربوطه را انتخاب کنید. پیشنهاد نام‌گذاری:

پروژه در Harbor منبع
dockerhub Docker Hub
ghcr ghcr.io
k8s registry.k8s.io
quay quay.io

۳. استفاده

# before
docker pull nginx:1.27
# after (official images live under "library/")
docker pull harbor.example.ir/dockerhub/library/nginx:1.27
docker pull harbor.example.ir/ghcr/aquasecurity/trivy-db:2

بخش دوم: Kubernetes بدون تغییر Manifestها

عوض کردن آدرس همه‌ی Imageها در همه‌ی Helm Chartها عملی نیست؛ به‌خصوص برای Chartهای آماده مثل kube-prometheus-stack. راه بهتر این است که containerd روی هر Node، درخواست‌های docker.io را خودش به Harbor بفرستد.

در containerd نسخه‌ی 1.7 مسیر پیکربندی را در /etc/containerd/config.toml فعال کنید:

[plugins."io.containerd.grpc.v1.cri".registry]
  config_path = "/etc/containerd/certs.d"

سپس برای هر Registry یک فایل hosts.toml بسازید:

# /etc/containerd/certs.d/docker.io/hosts.toml
server = "https://registry-1.docker.io"

[host."https://harbor.example.ir/v2/dockerhub"]
  capabilities = ["pull", "resolve"]
  override_path = true
# /etc/containerd/certs.d/registry.k8s.io/hosts.toml
server = "https://registry.k8s.io"

[host."https://harbor.example.ir/v2/k8s"]
  capabilities = ["pull", "resolve"]
  override_path = true
sudo systemctl restart containerd
# test from the node
sudo crictl pull nginx:1.27

حالا هر Pod که image: nginx:1.27 دارد، بی‌آنکه چیزی در Manifestش عوض شود، از Harbor دریافت می‌شود. این تنظیم را حتماً در Ansible یا ابزار IaC خودتان بنویسید تا Nodeهای جدید هم خودکار آن را داشته باشند.

بخش سوم: Nexus برای پکیج‌ها

Docker فقط نیمی از ماجراست. npm install، pip install و dotnet restore هم به اینترنت خارجی نیاز دارند. Sonatype Nexus Repository برای هر اکوسیستم یک Proxy Repository می‌سازد:

اکوسیستم Repository در Nexus منبع
npm npm-proxy https://registry.npmjs.org
PyPI pypi-proxy https://pypi.org
NuGet nuget-proxy https://api.nuget.org/v3/index.json
Maven maven-proxy https://repo1.maven.org/maven2/

برای هر کدام یک Group Repository هم بسازید که Proxy و پکیج‌های داخلی سازمان (Hosted) را با یک آدرس سرو کند.

تنظیم کلاینت‌ها:

# npm (.npmrc)
registry=https://nexus.example.ir/repository/npm-group/

# pip (/etc/pip.conf or ~/.config/pip/pip.conf)
[global]
index-url = https://nexus.example.ir/repository/pypi-group/simple
<!-- NuGet: nuget.config -->
<configuration>
  <packageSources>
    <clear />
    <add key="nexus" value="https://nexus.example.ir/repository/nuget-group/index.json" />
  </packageSources>
</configuration>

نکات نگهداری

  • Garbage Collection در Harbor را هفتگی زمان‌بندی کنید و برای پروژه‌های Proxy، Retention Policy بگذارید (مثلاً حذف Imageهایی که ۹۰ روز Pull نشده‌اند).
  • Storage را روی MinIO یا یک دیسک جدا بگذارید و از دیتابیس Harbor و Nexus بکاپ منظم بگیرید.
  • Vulnerability Scanning: Harbor به‌صورت داخلی از Trivy پشتیبانی می‌کند. اسکن خودکار هنگام Push را فعال کنید.
  • High Availability: اگر کل سازمان به این دو سرویس وابسته است، برای آن‌ها هم مانیتورینگ و Alert تعریف کنید. قطعی Harbor یعنی هیچ Podی نمی‌تواند Image جدید بگیرد.

جمع‌بندی

Harbor و Nexus برای تیم‌های ایرانی یک انتخاب لوکس نیستند؛ زیرساخت پایه‌اند. یک‌بار راه‌اندازی درست، Pipelineها را سریع‌تر، Deployها را قابل اعتماد و کل تیم را از نوسانات اینترنت بین‌الملل مستقل می‌کند.