WIUNIX ACADEMY
راهاندازی رجیستری خصوصی Docker با HTTPS و Nginx
صفحهٔ 4 از 5؛ مراحل قبلی و پیشنیازها را پیش از ادامه مرور کن.
آموزش متناسب با محیط تو
کجا اجرا میکنی؟
سیستمعامل و نسخه را انتخاب کن تا مراحل، دستورها و راهحلها برای همان محیط نمایش داده شوند.
آموزش متناسب با مقادیر تو
تنظیمات این آموزش
مقادیر نمونه را برای محیط خودت تنظیم کن؛ متن و دستورهای مرتبط با هم تغییر میکنند. رمز، کلید خصوصی و توکن وارد نکن. مقادیر فقط در همین زبانه نگهداری میشوند و به سرور یا لینک اشتراکگذاری فرستاده نمیشوند. پیش از اجرا، DNS، گواهیها و سیاست شبکهٔ واقعی را بررسی کن.
آیپی، دامنه یا پورت مثالها با محیط تو فرق دارد؟ دکمهٔ زیر را باز کن، مقادیر را تغییر بده و «اعمال در آموزش» را بزن؛ سپس دستورهای بهروزشده را کپی کن.
تنظیم مقادیر برای محیط من8 مقدار قابلتغییر
قدم بعدی
رد ورود نامعتبر را هم بررسی کنید
نبود رمز و رمز غلط را هر دو بررسی کنید. رمز غلط را فقط در درخواست تعاملی خصوصی وارد کنید؛ هدر Authorization یا خروجی helper را ذخیره نکنید. بعد از آزمون، با رمز درست دوباره وارد شوید. موفقیت login به معنی آزمون مجوز جداگانهٔ مخزن نیست؛ htpasswd چنین تفکیکی ندارد.
کلاینت لینوکسی
curl --silent --show-error --output /dev/null --write-out '%{http_code}
' 'https://registry.example.net/v2/'
docker --config "$HOME/.config/academy-registry-client" login 'registry.example.net' --username 'academy-publisher'
بدون رمز و با رمز غلط ورود رد میشود و با رمز درست دوباره موفق است.
قدم بعدی
ماندگاری داده پس از restart را اثبات کنید
روی VM، ارسالهای جدید را متوقف و برای پایان آپلود جاری صبر کنید؛ سپس فقط همین کانتینر را restart کنید. دوباره از کلاینت تمیز pull بگیرید و digest را مقایسه کنید. دریافت 401 بهتنهایی ماندگاری لایهها را ثابت نمیکند. این آزمون جای بازیابی بکاپ یا reboot نیست.
VM رجیستری
set -eu
sudo docker restart --time 90 'academy-registry'
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' 'https://registry.example.net/v2/'
401 سالم برمیگردد و pull تازه همان manifest و blobها را دریافت میکند.
قدم بعدی
خطای آپلود را از خطای ورود جدا کنید
برای 413 ابتدا سقف 1024 مگابایت هر درخواست و محدودیت پراکسیهای بالادست را بررسی کنید. توقف آپلود میتواند از buffering، HTTP/1.1، مهلت بیکاری 900 ثانیه، کمبود inode یا مجوز data باشد. برای 502 وضعیت کانتینر و listener را ببینید؛ برای 401 با رمز درست، قالب bcrypt، نام کاربر و restart پس از تعویض رمز مهماند.
اگر Location آپلود به HTTP یا نام داخلی رفت، ادامه ندهید. host و scheme را اصلاح کنید؛ insecure-registry راهحل نیست. خطای TLS را با نام گواهی، زنجیره، ساعت و CA مدیریتشده بررسی کنید. فقط وضعیت پالایششده را به اشتراک بگذارید؛ فایل auth و پیکربندی دارای secret قابل انتشار نیستند.
VM رجیستری
sudo docker inspect 'academy-registry' --format '{{.State.Status}} {{.State.ExitCode}}'
sudo stat -c '%a %u:%g %n' '/srv/academy-registry/data' '/srv/academy-registry/auth/htpasswd' '/srv/academy-registry/config/config.yml'
sudo df -h '/srv/academy-registry/data'
sudo df -i '/srv/academy-registry/data'
sudo nginx -t
curl --silent --show-error --dump-header - --output /dev/null 'https://registry.example.net/v2/'
علت مشخص میشود، بدون افشای اعتبارنامه یا کاهش حفاظت امنیتی.
قدم بعدی
بکاپ سازگار با توقف نویسنده تهیه کنید
پنجرهٔ توقف تعیین کنید، CI را از ارسال بازدارید و بعد از پایان آپلودها رجیستری را متوقف کنید. data و تنظیمات، auth و TLS باید از یک نقطهٔ سازگار برداشته شوند. آرشیو زیر محرمانه و فقط یک فایل واسط محلی است؛ آن را با سیستم بکاپ مصوب رمزگذاری و خارج از سرور منتقل کنید. کپی روی همان دیسک، بازیابی بحران نیست.
در طرح چندنمونهای، توقف یک کانتینر کافی نیست؛ همهٔ نویسندهها و وابستگیهای ذخیرهسازی باید هماهنگ شوند. بازیابی را روی VM مستقل با همان نسخه تمرین کنید، manifest و blobها و pull تمیز را بسنجید و سپس نوشتن را آزاد کنید. این مقاله انجام بازیابی واقعی را ادعا نمیکند.
VM رجیستری
set -eu
sudo docker stop --time 90 'academy-registry'
sudo test "$(sudo docker inspect --format '{{.State.Running}}' 'academy-registry')" = false
sudo python3 - <<'PY'
import os, subprocess
from pathlib import Path
root=Path('/srv/academy-registry')
dest=root/'recovery'/'consistent-backup.tar'
fd=os.open(dest,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600)
with os.fdopen(fd,'wb') as out:
subprocess.run(['tar','--numeric-owner','-C',str(root),'-cf','-','data','config','auth','tls'],stdout=out,check=True)
print('Stopped-writer snapshot created; transfer encrypted off-host before resuming')
PY
sudo docker start 'academy-registry'
آرشیو تازهٔ 0600 در حالت توقف نویسنده ساخته و انتقال امن خارج از سرور برنامهریزی میشود.
قدم بعدی
پیش از پاکسازی، رابطهٔ tag و manifest را بفهمید
حذف tag یا manifest با آزادشدن فضای blob فرق دارد. API حذف در تنظیمات فعلی خاموش است و برای push و pull لازم نیست. فعالکردن آن به تصمیم نگهداشت و مجوزدهی نیاز دارد؛ فایلهای data را دستی پاک نکنید. GC ابتدا ارجاعها را علامت میزند و بعد دادهٔ بیارجاع را حذف میکند؛ آپلود همزمان میتواند لایه را از بین ببرد.
پنل فقط dry-run است، آن هم با سرویس متوقف، دادهٔ فقطخواندنی و همان تصویر پینشده. خروجی نام مخزن را نشان میدهد و باید خصوصی بماند. GC مخرب بعد از بکاپ و تمرین بازیابی، اقدام نگهداری جداگانه است. readonly نیز با ویرایش فایل فعال نمیشود؛ باید همهٔ نویسندهها با این حالت restart شوند و رد نوشتن واقعاً دیده شود.
VM رجیستری
set -eu
sudo docker stop --time 90 'academy-registry'
sudo test "$(sudo docker inspect --format '{{.State.Running}}' 'academy-registry')" = false
sudo docker run --rm --network none --user '23153:23153' \
--read-only --cap-drop ALL --security-opt no-new-privileges --log-driver none \
--mount 'type=bind,src=/srv/academy-registry/data,dst=/var/lib/registry,readonly' \
--mount 'type=bind,src=/srv/academy-registry/auth,dst=/auth,readonly' \
--mount 'type=bind,src=/srv/academy-registry/config,dst=/etc/distribution,readonly' \
--entrypoint /bin/registry 'docker.io/library/registry:3.1.2@sha256:ddf754342cfc8acc51a56d5d0ab6af06826461864460636d8bd5c546dab2a7b8' \
garbage-collect --dry-run /etc/distribution/config.yml
sudo docker start 'academy-registry'
dry-run فقط نامزدها را گزارش میکند، چیزی حذف نمیشود و سرویس دوباره بالا میآید.
برگشت امن در صورت شکست
اگر نخستین reload شکست خورد، فقط فایل سایت تازه را به recovery منتقل کنید، syntax تنظیمات قبلی را بسنجید و همان را reload کنید. بکاند محلی خصوصی بماند. در شکست ارتقای رجیستری، قبل از برگشت تصویر، نوشتن را متوقف و تنظیمات و اسنپشات وضعیت شکستخورده را حفظ کنید؛ سازگاری قالب داده با نسخهٔ قبلی را از upstream بررسی کنید.
برای تعویض رمز، فایل bcrypt جایگزین را در محیط محافظتشده آماده، نسخهٔ قبلی را نگه دارید و پس از جایگزینی اتمیک، restart کنید. رد رمز قدیمی و پذیرش رمز جدید باید جدا بررسی شوند. حذف auth یا غیرفعالکردن اعتماد TLS، روش بازیابی نیست.