← شروع آموزش

WIUNIX ACADEMY

انتشار blue/green با Docker Compose؛ از healthcheck تا برگشت مسیر

صفحهٔ 2 از 3؛ قبل از ادامه، مراحل قبلی و چیزهایی رو که لازم داری مرور کن.

آموزش متناسب با محیط تو

کجا اجرا می‌کنی؟

سیستم‌عامل و نسخهٔ سرورت رو انتخاب کن تا مراحل، دستورها و راه‌حل‌های همون محیط رو ببینی.

Debian 13بررسی‌شده با مستندات رسمی ·

آموزش متناسب با مقادیر تو

تنظیمات این آموزش

مقادیر نمونه رو با مشخصات سرورت عوض کن تا متن و دستورها با هم تغییر کنن. رمز، کلید خصوصی و توکن اینجا وارد نکن. مقدارها فقط توی همین زبانه می‌مونن و به سرور یا لینک اشتراک‌گذاری فرستاده نمی‌شن. قبل از اجرا، DNS، گواهی‌ها و تنظیمات دسترسی شبکه رو روی سرورت بررسی کن.

اگر آی‌پی، دامنه یا پورت‌های نمونه با سرورت فرق دارن، بخش تنظیمات پایین رو باز کن. مقدارها رو عوض کن و «اعمال در آموزش» رو بزن؛ بعد دستورهای تازه رو کپی کن.

تنظیم مقادیر برای محیط من5 مقدار قابل‌تغییر
04

قدم بعدی

با image مشخص، blue و پراکسی رو بالا بیاریم

digest ثبت‌شدهٔ manifest چندمعماری در ۲۰۲۶-۱۱-۰۵ از فرادادهٔ Docker Official Image بررسی شده: Nginx پایدار 1.30.6 روی Alpine. اسم stable-alpine برای شناخت کاناله؛ digest محتوا رو ثابت می‌کنه، حتی اگر بعداً tag جابه‌جا بشه. pull و بررسی digest کاریه که خواننده انجام می‌ده، نه ادعای اجرای image روی همهٔ سیستم‌ها و معماری‌ها توسط نویسنده.

اول یک hard link از مسیر blue به active.conf می‌سازیم. کل پوشهٔ پراکسی mount می‌شه تا renameهای بعدی دیده بشن؛ bind کردن یک فایل تنها ممکنه inode قبلی رو نگه داره. هر دو فایل Compose رو اعتبارسنجی کن، کانتینر متوقف و شبکهٔ green رو بساز و بعد blue و پراکسی رو با شرط سلامت شروع کن. --wait فقط وضعیت running یا healthcheck تعریف‌شده رو می‌سنجه؛ نسخه‌ای که از ورودی پاسخ می‌ده رو جدا می‌بینیم.

bash

ماشین آزمایشی لینوکس؛ همان نشست Bash مجاز

sudo ln -- '/srv/academy-bluegreen-demo/proxy/versions/blue.route' '/srv/academy-bluegreen-demo/proxy/active.conf' || exit 1
docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' config --quiet || exit 1
docker_lab compose -p 'academybg-green' -f '/srv/academy-bluegreen-demo/green.yml' config --quiet || exit 1
docker_lab pull 'nginx:stable-alpine@sha256:0e52bd054126cdc040b1276c0af347aeb02a41b9cfe305d6094767ac30e97949' || exit 1
docker_lab image inspect 'nginx:stable-alpine@sha256:0e52bd054126cdc040b1276c0af347aeb02a41b9cfe305d6094767ac30e97949' --format '{{json .RepoDigests}}' || exit 1
docker_lab compose -p 'academybg-green' -f '/srv/academy-bluegreen-demo/green.yml' create || exit 1
docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' up -d --wait --wait-timeout 45 || exit 1
marker=$(curl --noproxy '*' --fail --silent --show-error --max-time 3 'http://127.0.0.1:18080/release') || exit 1
test "$marker" = BLUE || exit 1
printf 'Gateway release: %s\n' "$marker"
از کجا بفهمم درست انجام شده؟

هر دو فایل معتبرن، green هنوز شروع نشده، شرط سلامت blue و پراکسی موفقه و ورودی BLUE برمی‌گردونه. خطا یعنی نمونهٔ نیمه‌تمام رو بررسی کن.

05

قدم بعدی

green رو شروع کنیم و از سمت پراکسی هم ببینیمش

blue و پراکسی رو روشن نگه دار. فقط پروژهٔ green رو شروع کن و برای healthcheck خودش صبر کن. بعد متن نسخه رو یک بار از پورت loopback خودش و یک بار از داخل کانتینر پراکسی و نام green-app بگیر. بررسی دوم، وصل‌نبودن شبکهٔ خارجی یا alias اشتباه رو پیدا می‌کنه؛ healthcheck محلی نمی‌تونه این‌ها رو ثابت کنه.

این درخواست‌های کوچک فقط آمادگی HTTP همین نمونه رو می‌سنجن. اگر وابستگی بعداً خراب بشه، Nginx خودکار به blue برنمی‌گرده. healthcheck هم سازگاری migration، درست‌بودن نوشتن داده یا بی‌خطر بودن retry رو ثابت نمی‌کنه. فقط به‌خاطر دیدن healthy، ترافیک واقعی رو جابه‌جا نکن.

bash

ماشین آزمایشی لینوکس؛ همان نشست Bash مجاز

docker_lab compose -p 'academybg-green' -f '/srv/academy-bluegreen-demo/green.yml' up -d --wait --wait-timeout 45 || exit 1
marker=$(curl --noproxy '*' --fail --silent --show-error --max-time 3 'http://127.0.0.1:18082/release') || exit 1
test "$marker" = GREEN || exit 1
marker=$(docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' exec -T gateway wget -T 3 -q -O - http://green-app/release) || exit 1
test "$marker" = GREEN || exit 1
از کجا بفهمم درست انجام شده؟

green سالمه و هم مستقیم و هم از شبکهٔ پراکسی GREEN می‌ده؛ blue برای برگشت همچنان موجوده.

06

قدم بعدی

مسیر green رو انتخاب کنیم، بسنجیم و reload بدیم

در این نمونهٔ اختصاصی، اپراتور دیگری هم‌زمان فایل‌ها رو ویرایش نمی‌کنه. یک hard link تازه و rename داخل همون پوشه، active.conf روی دیسک رو اتمی عوض می‌کنه و برچسب SELinux فایل بررسی‌شده حفظ می‌شه. انتخاب فایل هنوز به معنی تغییر پراکسیِ در حال اجرا نیست. قبل از درخواست reload، Nginx با -t تنظیم انتخاب‌شده رو بررسی می‌کنه.

اگر اعتبارسنجی شکست بخوره، پنل مسیر blue رو روی دیسک برمی‌گردونه و بدون reload متوقف می‌شه. اگر بعد از اعتبارسنجی، فرمان reload خطا داد، هر دو نسخه رو روشن نگه دار و از بخش برگشت ادامه بده؛ ممکنه فایل دیسک و وضعیت اجرا متفاوت باشن. موفق‌شدن ارسال سیگنال هم هنوز نمی‌گه همهٔ درخواست‌ها به green می‌رسن؛ بعدش درخواست تازه می‌فرستیم.

bash

ماشین آزمایشی لینوکس؛ همان نشست Bash مجاز

sudo ln -- '/srv/academy-bluegreen-demo/proxy/versions/green.route' '/srv/academy-bluegreen-demo/proxy/active.conf.next' || exit 1
sudo mv -T -- '/srv/academy-bluegreen-demo/proxy/active.conf.next' '/srv/academy-bluegreen-demo/proxy/active.conf' || exit 1
if ! docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' exec -T gateway nginx -t; then
  sudo ln -- '/srv/academy-bluegreen-demo/proxy/versions/blue.route' '/srv/academy-bluegreen-demo/proxy/active.conf.restore' || exit 1
  sudo mv -T -- '/srv/academy-bluegreen-demo/proxy/active.conf.restore' '/srv/academy-bluegreen-demo/proxy/active.conf' || exit 1
  docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' exec -T gateway nginx -t
  exit 1
fi
docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' exec -T gateway nginx -s reload || exit 1
از کجا بفهمم درست انجام شده؟

انتخاب green معتبره و reload درخواست شده، یا بعد از شکست اعتبارسنجی، blue روی دیسک برگشته. موفقیت مسیر جدا بررسی می‌شه.

07

قدم بعدی

درخواست تازه رو ببین و نسخهٔ قبلی رو نگه دار

پنج درخواست جدا با Connection: close می‌فرستیم و فقط متن دقیق GREEN رو قبول می‌کنیم. پاسخ خطا یا رنگ قبلی، جابه‌جایی موفق حساب نمی‌شه. لاگ پراکسی و فایل انتخاب‌شده رو ببین؛ اگر reload هنوز در حال انجامه، بعد از مشاهدهٔ محدود همین بررسی‌ها رو تکرار کن، نه اینکه blue رو حذف کنی.

این پاسخ‌ها فقط همین پنج درخواست HTTP رو ثابت می‌کنن. اتصال keep-alive یا WebSocket قبلی و کار پس‌زمینه رو تخلیه نمی‌کنن. نسخهٔ قدیمی و قالب مسیر قبلی رو تا پایان مهلت برگشت و تخلیهٔ متناسب با برنامه نگه دار. این نمونه کار طولانی نداره و فرمان عمومیِ حذف نسخهٔ قبلی از محیط واقعی هم نمی‌ده.

bash

ماشین آزمایشی لینوکس؛ همان نشست Bash مجاز

for sample in 1 2 3 4 5; do
  marker=$(curl --noproxy '*' --fail --silent --show-error --max-time 3 --header 'Connection: close' 'http://127.0.0.1:18080/release') || exit 1
  printf 'sample=%s release=%s\n' "$sample" "$marker"
  test "$marker" = GREEN || exit 1
  sleep 1
done
docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' logs --tail 30 gateway
از کجا بفهمم درست انجام شده؟

پنج درخواست تازه از ورودی GREEN می‌گیرن؛ هر دو نسخه روشن و قالب برگشت موجوده.

08

قدم بعدی

با بررسی سلامت و مسیر، به blue برگردیم

این برگشتِ مسیر برای نمونهٔ بدون state است، نه برگشت داده. اول مطمئن شو خود blue هنوز مستقیم BLUE می‌ده. قالب قبلی رو انتخاب کن، پراکسی رو اعتبارسنجی و reload کن و بعد از ورودی دوباره BLUE بخواه. اگر خود blue سالم نیست، توقف کن و علتش رو ببین؛ رفتن به نسخهٔ قبلیِ خراب، بازیابی نیست.

انتخاب با hard link اگر فایل .next از تلاش قبلی مونده باشه، روی اون نمی‌نویسه. همون فایل مشخص رو بررسی و وضعیتش رو روشن کن، بعد دوباره تلاش کن. برای reload فقط پراکسی، پروژهٔ blue رو از نو نساز؛ up ممکنه کانتینرها رو هم جایگزین کنه یا هویت شبکه رو عوض کنه.

bash

ماشین آزمایشی لینوکس؛ همان نشست Bash مجاز

marker=$(curl --noproxy '*' --fail --silent --show-error --max-time 3 'http://127.0.0.1:18081/release') || exit 1
test "$marker" = BLUE || exit 1
sudo ln -- '/srv/academy-bluegreen-demo/proxy/versions/blue.route' '/srv/academy-bluegreen-demo/proxy/active.conf.next' || exit 1
sudo mv -T -- '/srv/academy-bluegreen-demo/proxy/active.conf.next' '/srv/academy-bluegreen-demo/proxy/active.conf' || exit 1
docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' exec -T gateway nginx -t || exit 1
docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' exec -T gateway nginx -s reload || exit 1
for sample in 1 2 3; do
  marker=$(curl --noproxy '*' --fail --silent --show-error --max-time 3 --header 'Connection: close' 'http://127.0.0.1:18080/release') || exit 1
  test "$marker" = BLUE || exit 1
  sleep 1
done
از کجا بفهمم درست انجام شده؟

نسخهٔ قبلی مستقل پاسخ می‌ده و بعد از reload بررسی‌شده، سه درخواست تازهٔ ورودی BLUE می‌گیرن.

به‌جای اجبار جابه‌جایی، همون شرط شکست‌خورده رو بررسی کن

از بررسی فقط‌خواندنیِ متناسب استفاده کن. هنگام پیدا کردن علت، هر دو پروژه و فایل‌هاشون رو نگه دار. SELinux یا AppArmor رو خاموش نکن، backend فایروال Docker رو عوض نکن، شنوندهٔ موجود رو حذف نکن و پاک‌سازی سراسری اجرا نکن.

Compose پیدا نمی‌شه یا لانچر قدیمی انتخاب شده

بسته و افزونه رو از همون تابع مدیریتیِ محلی ببین. به فرمان قدیمی docker-compose برنگرد، daemon فعال رو عوض نکن و برای موفق‌شدن نمونه از context دوردست استفاده نکن.

bash
docker_lab version
docker_lab compose version
docker_lab compose up --help
پراکسی به شبکهٔ green وصل نمی‌شه

قبل از شروع blue باید create پروژهٔ green موفق شده باشه. وضعیت همین پروژه و مالکیت شبکهٔ نام‌برده رو ببین. شبکهٔ خارجیِ حدسی با نام شخص دیگری نساز و پراکسی رو به شبکهٔ میزبان وصل نکن.

bash
docker_lab compose -p 'academybg-green' -f '/srv/academy-bluegreen-demo/green.yml' ps -a
docker_lab network inspect 'academybg-green_default'
green ناسالم می‌مونه یا درخواست مستقیم شکست می‌خوره

کانتینر تازه، لاگ و پورت bindشده رو ببین. سلامت اینجا به متن فایل و دسترسی mountشده وابسته است. روی میزبان SELinux، برچسب همین پوشهٔ تازه و منع مرتبط رو با مسئولش بررسی کن؛ پوشهٔ برنامهٔ موجود رو دوباره برچسب نزن.

bash
docker_lab compose -p 'academybg-green' -f '/srv/academy-bluegreen-demo/green.yml' ps -a
docker_lab compose -p 'academybg-green' -f '/srv/academy-bluegreen-demo/green.yml' logs --tail 40 green
sudo ls -ldZ '/srv/academy-bluegreen-demo/green'
ss -H -ltn '( sport = :18082 )'
green سالمه ولی ورودی هنوز blue یا 502 می‌ده

هم فایل روی دیسک و هم بررسی پراکسی رو ببین. endpoint محلیِ سالم نه رسیدن از شبکهٔ خارجی رو ثابت می‌کنه، نه DNS و نه بارگذاری مسیر تازه بعد از reload رو. blue رو حفظ کن و اگر جابه‌جایی قابل‌تأیید نیست، از برگشت صریح استفاده کن.

bash
sudo sha256sum '/srv/academy-bluegreen-demo/proxy/active.conf' '/srv/academy-bluegreen-demo/proxy/versions/blue.route' '/srv/academy-bluegreen-demo/proxy/versions/green.route'
docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' exec -T gateway nginx -t
docker_lab compose -p 'academybg-blue' -f '/srv/academy-bluegreen-demo/blue.yml' logs --tail 40 gateway
همهٔ آموزش‌های آکادمی ↗