
به اشتراک بگذارید

به اشتراک بگذارید
هاربر یا Harbor Registry یک رجیستری متنباز برای ایمیجهای کانتینر است. روی سرور خودتان مینشیند و کنار ایمیجها، نقش کاربر، اسکن آسیبپذیری و کش رجیستریهای عمومی را هم نگه میدارد. نصب آن با Docker Compose چند سرویس جدا را کنار هم بالا میآورد.
| جزء | کار آن | اگر از کار بیفتد (برداشت ما) |
|---|---|---|
| کانتینر nginx | ورودی پورت 80 و 443 | نه پورتال باز میشود، نه docker login |
| کانتینر harbor-core | سرور API و دسترسیها | ورود و کارهای مدیریتی شکست میخورند |
| کانتینر harbor-portal | رابط وب | فقط رابط وب از دست میرود |
| کانتینر registry | نگهداری لایهها، push و pull | ورود موفق، انتقال ایمیج ناموفق |
| کانتینر harbor-jobservice | صف کارهای پسزمینه | کارهای زماندار در صف میمانند |
| کانتینر harbor-db | پایگاهداده PostgreSQL | کاربرها و پروژهها در دسترس نیستند |
💡 چند کانتینر، یک harbor.yml
داده همه کانتینرها در /data میماند.
✅ روی سرور ایران بسته آفلاین را بگیرید؛ 403 را دور میزند، اما Proxy Cache نه.
✅ برای باز کردن Docker Hub روی خود سرور، راهنمای تحریم داکر روی سرور ایران را ببینید.
پیام unauthorized معمولاً از harbor-core میآید و push نیمهکاره از registry یا دیسک پر. ستون سوم جدول برداشت ما از نقش هر جزء است و مستند نیست.
📌 قطعههای این راهنما
◀️ اجزای هاربر؛ هر کانتینر چه کاری میکند
◀️ نصب با Docker Compose و فایل harbor.yml
◀️ گواهی SSL، کاربران و دسترسی پروژهها را تنظیم کنید
◀️ پروژه Proxy Cache و اسکن آسیبپذیری چطور کار میکنند؟

در Harbor Registry هر وظیفه یک کانتینر جدا دارد: لایهها در registry میمانند و فراداده در harbor-db. نامهای زیر همان container_name در فایل Compose نسخه 2.15 هستند.
درخواستهای مرورگر و docker اول به nginx میرسند و گواهی SSL هم روی همین کانتینر بار میشود؛ خطای گواهی را از اینجا دنبال کنید.
کانتینر harbor-core سرور API است و احراز هویت و پروژهها را مدیریت میکند؛ harbor-portal فقط رابط گرافیکی است. اگر صفحه ورود باز شد ولی ورود انجام نشد، لاگ core را بخوانید.
ذخیره و تحویل لایهها کار registry است، همان نرمافزار Distribution. اگر login موفق است ولی push وسط کار میماند، این کانتینر و فضای دیسک را بررسی کنید.
🔸 این انبار با registry-mirrors چه فرقی دارد؟
پروژه Proxy Cache هاربر دسترسی خودش را دارد، GHCR را هم پشتیبانی میکند و نشانی pull را صریح عوض میکند. کلید registry-mirrors در مقابل، به گفته مستندات Docker فقط Docker Hub را میرور میکند و روی کل Docker Engine اثر دارد. تنظیم میرور را در راهنمای تحریم داکر ببینید.
کانتینر harbor-jobservice صف کارهای پسزمینه مثل Replication است و redis کش و فراداده موقت کارها را نگه میدارد. کار گیرکرده در صف یعنی یکی از این دو مشکل دارد.
کانتینر harbor-db یک PostgreSQL برای فراداده کاربرها و پروژههاست. لایهها آنجا نیستند؛ پس پشتیبان باید هر دو را بگیرد.
کانتینر trivy-adapter فقط با --with-trivy ساخته میشود و harbor-log لاگ بقیه را در /var/log/harbor میزبان جمع میکند. وضعیت همه را در پوشه نصب ببینید:
sudo docker compose ps
طبق صفحه پیشنیازهای هاربر، Harbor Registry دستکم ۲ هسته CPU، ۴ گیگابایت رم و ۴۰ گیگابایت دیسک میخواهد و پیشنهادش ۴ هسته، ۸ و ۱۶۰ گیگابایت است. نسخه Docker Engine باید بالاتر از 20.10 و Compose بالاتر از 2.3 باشد. پورتهای 80 و 443 را باز کنید و رکورد DNS نام هاربر را به این سرور ببرید.
بسته آنلاین ایمیجهای هاربر را هنگام نصب از Docker Hub میکشد؛ بسته آفلاین آنها را دارد. از نسخه 2.15.0 هر فایل نصب در Releases گیتهاب امضای .sigstore.json دارد که با cosign 2 یا بالاتر بررسی میشود و خروجی درستش Verified OK است. اگر Docker نصب نیست، آموزش نصب Docker و Docker Compose روی اوبونتو 24.04 را ببینید.
V=v2.15.0
wget https://github.com/goharbor/harbor/releases/download/$V/harbor-offline-installer-$V.tgz
wget https://github.com/goharbor/harbor/releases/download/$V/harbor-offline-installer-$V.tgz.sigstore.json
cosign verify-blob --bundle harbor-offline-installer-$V.tgz.sigstore.json \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
--certificate-identity-regexp '^https://github.com/goharbor/harbor/.github/workflows/publish_release.yml@refs/tags/v.*$' \
harbor-offline-installer-$V.tgz
tar xzvf harbor-offline-installer-$V.tgz
cd harbor && cp harbor.yml.tmpl harbor.yml
در نسخه کپیشده فقط همین کلیدها را عوض کنید و بقیه خطوط را پاک نکنید. مقدارهای داخل <> را خودتان پر کنید:
hostname: <reg.example.ir> # نام DNS هاربر؛ localhost مجاز نیست
https:
port: 443
certificate: /data/cert/<reg.example.ir>.crt # فایلهایی که nginx بار میکند
private_key: /data/cert/<reg.example.ir>.key
# فقط در اولین راهاندازی خوانده میشود (پیشفرض: Harbor12345)
harbor_admin_password: <strong-admin-password>
database:
password: <strong-db-password> # پیشفرض قالب: root123
data_volume: /data # لایهها، پایگاهداده و redis روی میزبان
trivy:
skip_update: false # true یعنی Trivy پایگاه را دانلود نکند
اسکریپت نصب گواهی و کلید را از مسیرهای بخش https برای nginx کپی میکند و اگر نباشند متوقف میشود. پس گواهی CA معتبر یا خودامضای بخش بعد را اول در /data/cert بگذارید، بعد نصب را با اسکنر بزنید:
sudo mkdir -p /data/cert
sudo cp reg.example.ir.crt reg.example.ir.key /data/cert/
sudo ./install.sh --with-trivy
کلیدهای دیگر در مرجع فایل harbor.yml آمدهاند. برای تغییرهای بعدی این سه دستور را بزنید؛ ./prepare بدون --with-trivy اسکنر را حذف میکند و down دادههای /data را پاک نمیکند:
sudo docker compose down -v
sudo ./prepare --with-trivy
sudo docker compose up -d
⚠️ پوشه /data خودش کوچک نمیشود
حذف ایمیج فضای دیسک را آزاد نمیکند؛ این را مستندات Garbage Collection صریح گفتهاند. GC را از Administration و Clean Up دستی اجرا یا زمانبندی کنید. پروژههای Proxy Cache هم با هر pull تازه بزرگتر میشوند.

مستندات هاربر HTTP را فقط برای محیط آزمایشی بیاتصال به اینترنت میپذیرند؛ پس Harbor Registry را روی سرور واقعی با HTTPS بالا بیاورید. با گواهی CA معتبر مثل Let’s Encrypt کلاینتها تنظیم اضافه نمیخواهند؛ با CA خودتان هر کلاینت باید به آن اعتماد کند.
راهنمای HTTPS هاربر با openssl گواهی CA، کلید سرور، CSR و فایل v3.ext با subjectAltName را میسازد. حاصل ca.crt و دو فایل سرور است که در /data/cert گذاشتید.
روی هر کلاینت فقط ca.crt را در پوشهای به نام دقیق hostname بگذارید؛ Docker هر فایل .crt آنجا را CA ریشه میشناسد. کلید خصوصی سرور را هرگز روی کلاینت کپی نکنید. ریاستارت Docker کانتینرهای در حال اجرای آن سرور را متوقف میکند:
sudo mkdir -p /etc/docker/certs.d/reg.example.ir/
sudo cp ca.crt /etc/docker/certs.d/reg.example.ir/
sudo systemctl restart docker
🔸 اولین docker login روی HTTPS
نشانی هاربر نباید در insecure-registries فایل /etc/docker/daemon.json باشد. بعد docker login reg.example.ir را بزنید؛ با پورت غیر 443، :port را در login و نام پوشه certs.d بیاورید.
اگر رمز را در harbor.yml عوض نکرده باشید، ورود اول با admin و Harbor12345 است. هر push به یک پروژه نیاز دارد و پروژه خصوصی فقط به اعضایش اجازه pull میدهد. نقشهای هر پروژه:
برای CI/CD حساب ربات پروژه بسازید. این حساب با secret وارد میشود، به رابط وب راه ندارد و نامش <prefix><project_name>+<account_name> است.

پروژه Proxy Cache در Harbor Registry پروژهای است که به یک رجیستری بالادست وصل شده و push نمیپذیرد. به گفته مستندات Proxy Cache، اولین pull هر ایمیج را از بالادست میگیرد و نگه میدارد. بعد manifest را مقایسه میکند؛ با قطع بالادست نسخه کششده را میدهد و اگر ایمیج در بالادست نباشد، چیزی نمیدهد.
داروخانهای دارو را بار اول از پخشکننده سفارش میدهد و روی قفسه نگه میدارد. پروژه Proxy Cache همان قفسه است، اسکن Trivy نگاه به تاریخ انقضاست و نقشها تعیین میکنند چه کسی به قفسه پشتی دست بزند.
خروجی Docker برای ایمیج رسمی debian نام docker.io/library/debian است؛ پس بخش library را هم بنویسید. خط دوم این قاعده را برای پروژه فرضی dockerhub نشان میدهد:
docker pull <harbor_server_name>/<proxy_project_name>/goharbor/harbor-core:dev
docker pull reg.example.ir/dockerhub/library/debian:latest
کش فقط وقتی پر میشود که خود سرور هاربر به بالادست برسد؛ اگر Docker Hub به IP سرورتان 403 بدهد، ایمیج کشنشده تحویل نمیشود. هاربر برای هر پروژه Proxy Cache سیاست نگهداری ۷ روزه میسازد که در قطعی طولانی ممکن است ایمیج لازم را از کش حذف کند؛ آن را با نیازتان تنظیم کنید. درخواست HEAD برای بررسی تازگی در سهمیه Docker Hub شمرده نمیشود، اما دریافت لایه تازه شمرده میشود.
اسکن را دستی یا با زمانبندی اجرا کنید. در فایل نمونه 2.15، پایگاه آسیبپذیری از ghcr.io/aquasecurity/trivy-db میآید. بدون دسترسی به آن، skip_update را true کنید و trivy.db و metadata.json را از آرشیو trivy-offline.tar.gz در /data/trivy-adapter/trivy/db میزبان بگذارید؛ Compose این پوشه را به /home/scanner/.cache/trivy/db کانتینر وصل میکند.
اولین docker login معمولاً سر گواهی میایستد و اولین push سر نام پروژه؛ حساب ربات هم نوبت CI/CD است.
موتور Docker آن سرور به CA اعتماد ندارد. فقط ca.crt را در /etc/docker/certs.d/ و پوشهای همنام hostname بگذارید و Docker را ریاستارت کنید.
پروژه عمومی library از ابتدا هست و push میپذیرد، اما برای ایمیجهای داخلی پروژه خصوصی بسازید.
از حساب ربات پروژه که فقط در همان پروژه کار میکند. ساختن آن نقش Project Admin میخواهد.
خیر. ایمیجهای داخلی را در یک پروژه معمولی جدا نگه دارید.
ایمیجهای کششده را میدهد، تا وقتی سیاست ۷ روزه حذفشان نکرده باشد. ایمیج pullنشده در دسترس نیست.
این مقدار فقط در اولین راهاندازی خوانده میشود. رمز را از رابط وب عوض کنید.
لایههای بیاستفاده فقط با Garbage Collection پاک میشوند. آن را زمانبندی کنید.
جمعبندی؛ پیش از اولین push در Harbor Registry اینها را مرور کنید. بسته آفلاین را بگیرید و امضایش را با cosign بررسی کنید. گواهی و کلید را پیش از install.sh در /data/cert بگذارید و رمزهای پیشفرض را روز اول عوض کنید. روی کلاینتها فقط ca.crt را بگذارید و بعد از هر تغییر harbor.yml، prepare را با –with-trivy بزنید. پروژه Proxy Cache دانلودهای تکراری را کم میکند، ولی فقط چیزی را میدهد که خود هاربر یک بار گرفته و سیاست نگهداری هنوز حذفش نکرده باشد. GC را زمانبندی کنید، در CI/CD حساب ربات به کار ببرید و هر خطا را با نام کانتینر مسئولش دنبال کنید.
🚀 اگر هنوز ایمیجی به سرور نمیرسد
پیش از هاربر، مسیر دریافت ایمیج روی سرور ایران باید باز باشد. دکمه زیر به راهنمایی میرسد که علت خطای 403 و راههای پایدار دریافت ایمیج را توضیح میدهد.
ایمیجهای تیم شما امروز کجا نگهداری میشوند و چند نفر در آن مخزن push میکنند؟ در بخش نظرات بنویسید.
منابع