- مقدمه
- پیشنیازها
- مرحله 1 — نصب و پیکربندی Docker Registry
- مرحله ۲ — راهاندازی Port Forwarding در Nginx
- مرحله ۳ — راهاندازی احراز هویت (Authentication)
- مرحله ۴ — اجرای Docker Registry به عنوان سرویس
- مرحله ۵ — افزایش حداکثر حجم آپلود در Nginx
- مرحله ۶ — ارسال (Push) به رجیستری Docker خصوصی
- مرحله ۷ — Pull کردن از رجیستری خصوصی Docker
- نتیجهگیری

چگونه یک رجیستری خصوصی داکر را در اوبونتو اجرا و راه اندازی کنیم
مقدمه
Docker Registry یک برنامه است که مدیریت ذخیرهسازی و تحویل ایمیجهای کانتینر داکر را بر عهده دارد. رجیستریها ایمج های کانتینر را متمرکز کرده و زمان ساخت را برای توسعهدهندگان کاهش میدهند. ایمیجهای داکر محیط اجرایی یکسانی را از طریق مجازیسازی تضمین میکنند، اما ساخت یک ایمیج ممکن است نیازمند صرف زمان زیادی باشد. به عنوان مثال، به جای نصب جداگانه وابستگیها و پکیجها برای استفاده از داکر، توسعهدهندگان میتوانند یک ایمیج فشرده از رجیستری دانلود کنند که شامل تمام اجزای موردنیاز است. علاوه بر این، توسعهدهندگان میتوانند با استفاده از ابزارهای یکپارچهسازی مستمر مانند TravisCI، ارسال خودکار ایمیجها به رجیستری را انجام دهند تا ایمیجها را در زمان تولید و توسعه بدون دردسر بهروزرسانی کنند.
Docker Hub یک رجیستری عمومی رایگان است که میتواند میزبان ایمیجهای سفارشی داکر شما باشد، اما در برخی موارد ممکن است نخواهید ایمیج شما به صورت عمومی در دسترس باشد. ایمیجها معمولاً شامل تمام کدی هستند که برای اجرای یک برنامه مورد نیاز است، بنابراین استفاده از یک رجیستری خصوصی هنگام استفاده از نرمافزار اختصاصی میتواند ترجیح داده شود.
در این آموزش، شما رجیستری خصوصی داکر خودتان را راهاندازی و ایمنسازی خواهید کرد. شما از Docker Compose برای تعریف تنظیماتی که کانتینرهای داکر شما را اجرا میکنند استفاده خواهید کرد، و از Nginx برای هدایت ترافیک سرور از اینترنت به کانتینر در حال اجرای داکر بهره خواهید برد. پس از اتمام این آموزش، قادر خواهید بود یک ایمیج سفارشی داکر را به رجیستری خصوصی خود ارسال کرده و آن را به صورت ایمن از یک سرور راه دور دریافت (pull) کنید.
پیشنیازها
برای تکمیل این آموزش، به موارد زیر نیاز خواهید داشت:
- دو سرور Ubuntu 22.04 که با دنبال کردن راهنمای «تنظیمات اولیه سرور اوبونتو 22.04» پیکربندی شده باشند، شامل:
- یک کاربر غیرریشه با دسترسی sudo
- یک فایروال فعال , یکی از این سرورها میزبان Docker Registry خصوصی شما خواهد بود و دیگری به عنوان کلاینت استفاده میشود.
- نصب Docker روی هر دو سرور، که میتوانید با دنبال کردن مراحل ۱ و ۲ از راهنمای «نصب و استفاده از Docker در Ubuntu 22.04» انجام دهید.
در سرور میزبان، به موارد زیر نیاز خواهید داشت:
- نصب Docker Compose روی سرور میزبان، که میتوانید با دنبال کردن مرحله ۱ از راهنمای «نصب و استفاده از Docker Compose در Ubuntu 22.04» انجام دهید.
- نصب Nginx روی سرور میزبان، که میتوانید با دنبال کردن مراحل راهنمای «نصب Nginx در Ubuntu 22.04» انجام دهید.
- ایمنسازی Nginx با Let’s Encrypt روی سرور میزبان برای رجیستری خصوصی Docker، که میتوانید با دنبال کردن راهنمای «ایمنسازی Nginx با Let’s Encrypt در Ubuntu 22.04» انجام دهید.
حتماً در مرحله ۴، تمام ترافیک را از HTTP به HTTPS هدایت (redirect) کنید. - یک نام دامنه ثبتشده که به سروری که رجیستری خصوصی Docker روی آن میزبانی میشود اشاره میکند. شما این را به عنوان بخشی از پیشنیاز Let’s Encrypt تنظیم خواهید کرد. در این آموزش، به آن با نام
your_domain
اشاره خواهیم کرد.
مرحله 1 — نصب و پیکربندی Docker Registry
اجرای داکر در خط فرمان برای شروع کار و تست کانتینرها مفید است، اما وقتی پای استقرارهای بزرگ با کانتینرهای متعدد که به صورت موازی اجرا میشوند به میان میآید، میتواند دشوار و پیچیده شود.
با Docker Compose، شما یک فایل .yml
مینویسید تا تنظیمات هر کانتینر و اطلاعات موردنیاز برای ارتباط بین کانتینرها را تعیین کنید. میتوانید با ابزار docker compose
دستورات را به تمام اجزای برنامه بدهید و آنها را به صورت یک گروه کنترل کنید.
Docker Registry خود یک برنامه با اجزای متعدد است، بنابراین برای مدیریت آن از Docker Compose استفاده خواهید کرد. برای شروع یک نمونه از رجیستری، یک فایل docker-compose.yml
تنظیم خواهید کرد تا آن را تعریف کند و مکان ذخیرهسازی دادهها در دیسک را مشخص نماید.
شما پیکربندی را در دایرکتوریای به نام docker-registry
روی سرور میزبان ذخیره خواهید کرد. با اجرای دستور زیر آن را ایجاد کنید:
mkdir ~/docker-registry
سپس وارد آن شوید:
cd ~/docker-registry
سپس یک زیرپوشه به نام data
بسازید، جایی که رجیستری شما ایمیجها را ذخیره خواهد کرد:
mkdir data
یک فایل به نام docker-compose.yml
ایجاد و باز کنید:
nano docker-compose.yml
خطوط زیر را اضافه کنید که یک نمونه پایه از Docker Registry را تعریف میکنند:
~/docker-registry/docker-compose.yml
version: '3'
services:
registry:
image: registry:latest
ports:
- "5000:5000"
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./data:/data
ابتدا، اولین سرویس را با نام registry
نامگذاری میکنید و ایمیج آن را registry
با آخرین نسخه تنظیم میکنید. سپس در قسمت ports
، پورت ۵۰۰۰ روی میزبان را به پورت ۵۰۰۰ در کانتینر نگاشت میکنید، که این امکان را میدهد که درخواست به پورت ۵۰۰۰ روی سرور ارسال شده و به رجیستری منتقل شود.
در بخش environment
، متغیر REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY
را روی /data
تنظیم میکنید تا مشخص شود دادهها در کدام حجم ذخیره شوند. سپس، در بخش volumes
، دایرکتوری /data
روی سیستم فایل میزبان را به /data
در کانتینر نگاشت میکنید که به صورت passthrough عمل میکند. در واقع دادهها روی سیستم فایل میزبان ذخیره خواهند شد.
فایل را ذخیره کرده و ببندید.
اکنون میتوانید پیکربندی را با اجرای دستور زیر آغاز کنید:
docker compose up
کانتینر رجیستری و وابستگیهای آن دانلود و راهاندازی خواهند شد.
خروجی:
[+] Running 2/2
⠿ Network docker-registry_default Created 0.1s
⠿ Container docker-registry-registry-1 Created 0.1s
Attaching to docker-registry-registry-1
docker-registry-registry-1 | time="2022-11-19T14:31:20.40444638Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown"
docker-registry-registry-1 | time="2022-11-19T14:31:20.404960549Z" level=info msg="redis not configured" go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown"
docker-registry-registry-1 | time="2022-11-19T14:31:20.412312462Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown"
docker-registry-registry-1 | time="2022-11-19T14:31:20.412803878Z" level=info msg="Starting upload purge in 52m0s" go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown"
docker-registry-registry-1 | time="2022-11-19T14:31:20.41296431Z" level=info msg="listening on [::]:5000" go.version=go1.16.15 instance.id=4fb8d420-eaf8-4a69-b740-bdc94fa52d91 service=registry version="v2.8.1+unknown"
...
شما در ادامهی این آموزش به پیام هشدار No HTTP secret provided
رسیدگی خواهید کرد.
آخرین خط خروجی نشان میدهد که رجیستری با موفقیت راهاندازی شده و در حال گوش دادن روی پورت ۵۰۰۰ است.
برای متوقف کردن اجرای آن، میتوانید کلیدهای CTRL+C
را فشار دهید.
در این مرحله، یک پیکربندی Docker Compose ایجاد کردید که یک Docker Registry را روی پورت ۵۰۰۰ راهاندازی میکند. در مراحل بعدی، آن را روی دامنه خود منتشر کرده و احراز هویت را تنظیم خواهید کرد.
مرحله ۲ — راهاندازی Port Forwarding در Nginx
به عنوان بخشی از پیشنیازها، شما HTTPS را روی دامنهتان فعال کردهاید. برای اینکه Docker Registry ایمن خود را از طریق این دامنه در دسترس قرار دهید، باید Nginx را طوری پیکربندی کنید که ترافیک را از دامنه به کانتینر رجیستری هدایت کند.
قبلاً فایل پیکربندی سرور خود را در مسیر /etc/nginx/sites-available/your_domain
تنظیم کردهاید. برای ویرایش آن، دستور زیر را اجرا کنید:
sudo nano /etc/nginx/sites-available/your_domain
در فایل بازشده، بلوک location
موجود را پیدا کنید:
...
location / {
...
}
...
شما باید ترافیک را به پورت ۵۰۰۰ هدایت کنید، جایی که رجیستری منتظر ترافیک خواهد بود. همچنین لازم است هدرهایی را به درخواست ارسالی اضافه کنید که اطلاعات بیشتری دربارهی درخواست فراهم کند. محتوای موجود در بلوک location
را با خطوط زیر جایگزین کنید:
location / {
# عدم پذیرش اتصال از Docker نسخههای ۱.۵ و پایینتر
# docker قبل از نسخه ۱.۶.۰ user agent را به درستی تنظیم نمیکرد، بررسی "Go *" برای جلوگیری از دسترسی برنامههای نوشتهشده با Go
if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
return 404;
}
proxy_pass http://localhost:5000;
proxy_set_header Host $http_host; # برای سازگاری با docker client
proxy_set_header X-Real-IP $remote_addr; # ارسال IP واقعی کلاینت
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 900;
}
بلوک if
user agent درخواست را بررسی میکند تا مطمئن شود که نسخهی کلاینت Docker بالاتر از ۱.۵ است و درخواست از یک اپلیکیشن نوشتهشده با Go نیست.
فایل را ذخیره کرده و ببندید، سپس Nginx را ریستارت کنید تا تغییرات اعمال شود:
sudo systemctl restart nginx
اگر پیغام خطا دریافت کردید، پیکربندی واردشده را دوباره بررسی کنید.
اکنون برای بررسی اینکه آیا Nginx به درستی ترافیک را به کانتینر رجیستری هدایت میکند، کانتینر را اجرا کنید:
docker compose up
سپس در مرورگر به آدرس زیر بروید:
https://your_domain/v2
مرورگر یک شیء JSON خالی نمایش میدهد:
{}
در ترمینال خروجی مشابه زیر را دریافت خواهید کرد:
GET /v2 HTTP/1.0 → 301
GET /v2/ HTTP/1.0 → 200
این نشان میدهد که درخواست به /v2/ ارسال شده و رجیستری پاسخ موفق داده است (200 OK
).
با فشردن CTRL+C
اجرای کانتینر را متوقف کنید.
مرحله ۳ — راهاندازی احراز هویت (Authentication)
Nginx به شما اجازه میدهد احراز هویت HTTP را برای سایتهایی که مدیریت میکند، تنظیم کنید. برای محدود کردن دسترسی به Docker Registry، از این قابلیت استفاده میکنیم.
برای این کار ابتدا ابزار htpasswd
را نصب کنید:
sudo apt install apache2-utils -y
فایلی برای ذخیرهی اطلاعات احراز هویت ایجاد کنید:
mkdir ~/docker-registry/auth
cd ~/docker-registry/auth
اکنون اولین کاربر را ایجاد کنید (بهجای username
، نام کاربری دلخواه را وارد کنید):
htpasswd -Bc registry.password username
هنگام درخواست، رمز عبور را وارد کنید. ترکیب نام کاربری و رمز در فایل registry.password
ذخیره میشود.
اگر خواستید کاربران بیشتری اضافه کنید، این دستور را بدون گزینه
-c
اجرا کنید:htpasswd -B registry.password newuser
اکنون فایل docker-compose.yml
را ویرایش کنید تا مشخص کنید رجیستری از این فایل برای احراز هویت استفاده کند:
nano ~/docker-registry/docker-compose.yml
خطوط زیر را به بخش environment
و volumes
اضافه کنید:
version: '3'
services:
registry:
image: registry:latest
ports:
- "5000:5000"
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry
REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
volumes:
- ./auth:/auth
- ./data:/data
این پیکربندی، سیستم احراز هویت را فعال میکند، محل فایل رمز عبور را مشخص کرده و آن را داخل کانتینر رجیستری در مسیر /auth
قرار میدهد.
فایل را ذخیره کرده و ببندید.
برای آزمایش، به دایرکتوری اصلی پروژه بروید و رجیستری را اجرا کنید:
cd ~/docker-registry
docker compose up
اکنون در مرورگر، دوباره به دامنهی خود مراجعه کنید. این بار از شما نام کاربری و رمز خواسته میشود. پس از وارد کردن اطلاعات معتبر، صفحهی {}
نمایش داده خواهد شد.
با CTRL+C
اجرای کانتینر را متوقف کنید.
در این مرحله، رجیستری شما امن شده و فقط با احراز هویت قابل دسترسی است. در مرحله بعد، آن را بهصورت یک سرویس پسزمینهای و ماندگار تنظیم خواهیم کرد.
مرحله ۴ — اجرای Docker Registry به عنوان سرویس
برای اینکه رجیستری شما بعد از ریبوت سیستم یا کرش دوباره اجرا شود، میتوانید به Docker Compose دستور دهید که همیشه آن را روشن نگه دارد.
فایل docker-compose.yml
را باز کنید:
nano docker-compose.yml
خط زیر را به بلاک registry:
اضافه کنید:
...
registry:
restart: always
...
تنظیم گزینه restart: always
باعث میشود کانتینر حتی بعد از ریبوت شدن سیستم یا در صورت کرش، به طور خودکار دوباره اجرا شود.
فایل را ذخیره و ببندید.
اکنون رجیستری را در پسزمینه اجرا کنید:
docker compose up -d
رجیستری حالا در پسزمینه اجرا میشود و حتی اگر ترمینال یا اتصال SSH را ببندید، همچنان فعال باقی خواهد ماند.
مرحله ۵ — افزایش حداکثر حجم آپلود در Nginx
از آنجا که ایمیجهای Docker ممکن است حجم بالایی داشته باشند، باید محدودیت پیشفرض آپلود فایل در Nginx را افزایش دهید. مقدار پیشفرض ۱ مگابایت است که برای ایمیجهای Docker کافی نیست.
فایل اصلی پیکربندی Nginx را باز کنید:
sudo nano /etc/nginx/nginx.conf
در بخش http {
خط زیر را اضافه کنید:
http {
client_max_body_size 16384m;
...
}
این خط اندازه مجاز فایلهای ارسالی را به ۱۶ گیگابایت افزایش میدهد.
فایل را ذخیره کرده و ببندید، سپس Nginx را ریستارت کنید:
sudo systemctl restart nginx
اکنون میتوانید ایمیجهای حجیم را بدون خطا به رجیستری خود ارسال کنید.
مرحله ۶ — ارسال (Push) به رجیستری Docker خصوصی
اکنون که رجیستری شما فعال است و میتواند فایلهای حجیم را قبول کند، میتوانید یک ایمیج را به آن Push کنید. برای آزمایش، از ایمیج ubuntu
موجود در Docker Hub استفاده میکنیم.
در یک ترمینال جدید، دستور زیر را اجرا کنید:
docker run -t -i ubuntu /bin/bash
فلگهای -t
و -i
دسترسی تعاملی (interactive shell) به داخل کانتینر را فراهم میکنند.
داخل کانتینر، یک فایل به نام SUCCESS
ایجاد کنید:
touch /SUCCESS
این کار باعث میشود که کانتینر شخصیسازیشده باشد.
برای خروج از کانتینر:
exit
اکنون از این کانتینر شخصیسازیشده یک ایمیج جدید بسازید:
docker commit $(docker ps -lq) test-image
سپس وارد رجیستری خصوصی خود شوید:
docker login https://your_domain
نام کاربری و رمزی را که در مرحله ۳ ساختید وارد کنید.
خروجی به شکل زیر خواهد بود:
Login Succeeded
اکنون ایمیج را تگ کنید تا قابل ارسال به رجیستری باشد:
docker tag test-image your_domain/test-image
و در نهایت ایمیج را Push کنید:
docker push your_domain/test-image
خروجی مشابه زیر خواهد بود:
Using default tag: latest
The push refers to a repository [your_domain/test-image]
1cf9c9034825: Pushed
f4a670ac65b6: Pushed
latest: digest: sha256:...
شما اکنون تأیید کردهاید که:
- احراز هویت به درستی انجام شده است.
- کاربران معتبر میتوانند ایمیجه را به رجیستری ارسال کنند.
در ادامه میتوانید بررسی کنید که آیا میتوان این ایمیج را از رجیستری نیز Pull کرد یا نه.
مرحله ۷ — Pull کردن از رجیستری خصوصی Docker
حالا که ایمیج خود را به رجیستری خصوصی Push کردهاید، میخواهید از آن Pull (دریافت) کنید.
ابتدا در سرور اصلی وارد رجیستری شوید:
docker login https://your_domain
نام کاربری و رمز عبوری که در مرحله قبل ساختید را وارد کنید.
سپس ایمیج تستی را Pull کنید:
docker pull your_domain/test-image
Docker ایمیج را دریافت خواهد کرد. حالا برای اجرای کانتینر، دستور زیر را بزنید:
docker run -it your_domain/test-image /bin/bash
این دستور پوسته (shell) کانتینر را بارگذاری میکند.
برای دیدن فایلهای موجود:
ls
در لیست فایلها باید فایل SUCCESS
که قبلاً ایجاد کرده بودید، مشاهده شود:
SUCCESS bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
وجود فایل SUCCESS
تأیید میکند که این دقیقاً همان ایمیجی است که خودتان ساخته و Push کردهاید.
برای خروج از کانتینر:
exit
نتیجهگیری
در این آموزش، یک رجیستری خصوصی Docker راهاندازی کردید، احراز هویت را پیکربندی نمودید، محدودیت آپلود را افزایش دادید و یک ایمیج سفارشی را Push و Pull کردید.
اکنون میتوانید از این رجیستری برای ذخیره ایمیجهای اختصاصی پروژههایتان استفاده کنید. همچنین میتوانید با استفاده از ابزارهای CI مانند TravisCI، ارسال خودکار ایمیج ها را به رجیستری تنظیم کنید.
استفاده از کانتینرهای Docker در روند توسعه، تضمین میکند که برنامه شما در هر محیطی (توسعه، تست یا تولید) رفتار یکسانی داشته باشد.
برای یادگیری بیشتر در مورد ساخت Dockerfile های بهینه، به مستندات رسمی Best Practices for Writing Dockerfiles مراجعه کنید.
منبع DigitalOcean