کارشناس در کنار لپ‌تاپ، مسیر دسترسی به پورت کانتینر را روی تخته بررسی می‌کند.

WIUNIX ACADEMY

پورت کانتینر باز مانده، با اینکه UFW فعال است؛ علت و راه‌حل

بررسی کنید درخواست اینترنتی از چه مسیری به کانتینر می‌رسد. سپس پورت یک سرویس HTTP موجود را فقط روی خود سرور در دسترس بگذارید و با آزمایش داخلی و بیرونی، نتیجه را بسنجید.

متوسط20 دقیقه مطالعهبه‌روزرسانی
محیطت را انتخاب کن

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

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

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

RHEL 10بررسی‌شده با مستندات رسمی ·

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

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

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

آی‌پی، دامنه یا پورت مثال‌ها با محیط تو فرق دارد؟ دکمهٔ زیر را باز کن، مقادیر را تغییر بده و «اعمال در آموزش» را بزن؛ سپس دستورهای به‌روز‌شده را کپی کن.

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

از اینجا شروع کن

در پایان چه چیزی خواهی داشت؟

علت دسترسی مستقیم به پورت کانتینر را پیدا کنید، دسترسی اضافه را ببندید و مطمئن شوید مسیر اصلی ورود به اپلیکیشن همچنان سالم است.

01درخواست بیرونیIP عمومی → پورت منتشرشده → NAT Docker
02بک‌اند خصوصیپروکسی میزبان → 127.0.0.1:8080 → 80
03بررسی نتیجهنگاشت واقعی + پاسخ محلی + آزمایش از شبکه‌ای دیگر
سیستم‌عامل‌ها و نسخه‌های پوشش‌داده‌شده

این راهنما بر پایهٔ مستندات Docker نوشته شده و برای Docker Engine نسخهٔ ۲۸ یا جدیدتر با دسترسی root، شبکهٔ bridge با NAT و پروژهٔ تک‌فایلی Compose نسخهٔ ۲ است. مسیرهای Ubuntu، Debian و RHEL جداگانه بررسی شده‌اند؛ نصب و اجرای عملی روی همهٔ این سیستم‌ها انجام نشده است.

قبل از شروع

  • یک سرویس HTTP که هم‌اکنون با Compose تک‌فایلی روی Docker Engine نسخهٔ ۲۸ یا جدیدتر اجرا می‌شود؛ Docker باید با دسترسی root کار کند و شبکه از نوع bridge با NAT باشد.
  • دسترسی مسئول استقرار، ابزارهای curl، Python 3 و ویرایشگر روی سرور، یک کامپیوتر در شبکه‌ای دیگر و فرصت هماهنگ‌شده برای وقفهٔ کوتاه سرویس.
  • یک سرویس HTTP که هم‌اکنون با Compose تک‌فایلی روی Docker Engine نسخهٔ ۲۸ یا جدیدتر اجرا می‌شود؛ Docker باید با دسترسی root کار کند و شبکه از نوع bridge با NAT باشد.
  • دسترسی مسئول استقرار، ابزارهای curl، Python 3 و ویرایشگر روی سرور، یک کامپیوتر در شبکه‌ای دیگر و فرصت هماهنگ‌شده برای وقفهٔ کوتاه سرویس.
  • Docker Engine نسخهٔ ۲۸ یا جدیدتر با دسترسی root و Compose نسخهٔ ۲ باید از قبل طبق روش مخصوص RHEL نصب باشند؛ این مسیر برای Podman یا بستهٔ podman-docker نیست.
  • ابزارهای curl، Python 3، nano، کلاینت OpenSSH، coreutils و iproute لازم‌اند. مدیریت firewalld همچنان با مسئول سرور است.

firewalld فعال است؛ مسیر ترافیک Docker را هم بررسی کنید

در RHEL معمولاً با firewalld کار می‌کنید، نه UFW. طبق مستندات Docker، اگر مدیریت iptables یا ip6tables آن فعال باشد و firewalld هم کار کند، Docker یک zone به نام docker با هدف ACCEPT و سیاستی به نام docker-forwarding می‌سازد. وضعیت واقعی را بررسی کنید؛ قاعدهٔ یک پورت روی میزبان، همهٔ مسیرهای عبور ترافیک کانتینر را نشان نمی‌دهد.

در ادامه، انتشار همان سرویس Compose را به آدرس محلی محدود می‌کنیم و دسترسی داخلی و بیرونی را می‌سنجیم. هیچ zoneای حذف نمی‌شود و فایروال میزبان عوض نمی‌شود. سازوکار firewalld را هم معادل قواعد UFW فرض نکنید.

پیش از شروع، نوع استقرار را بررسی کنید

این روش برای یک سرور لینوکسی با Docker Engine نسخهٔ ۲۸ یا جدیدتر و Compose نسخهٔ ۲ نوشته شده است. Docker باید با دسترسی root اجرا شود، شبکهٔ کانتینر bridge با NAT معمول باشد و پروژه فقط یک فایل Compose داشته باشد. باید اجازهٔ بازسازی سرویس موردنظر را در زمان تعیین‌شده داشته باشید.

اگر استقرار با چند فایل Compose، فایل override، profile یا گزینه‌های اختصاصی پروژه انجام می‌شود، تغییر را از همان روال استقرار پیش ببرید. این دستورها برای Swarm، شبکه‌های host و macvlan/ipvlan، حالت rootless، Docker Desktop یا مسیریابی مستقیم کانتینرها مناسب نیستند. پروکسی‌ای هم که داخل کانتینر دیگری اجرا می‌شود باید از شبکهٔ خصوصی مشترک به بک‌اند برسد؛ آدرس لوپ‌بک آن به خود میزبان اشاره نمی‌کند.

نشست SSH را باز نگه دارید و مطمئن شوید از کنسول هم می‌توانید به سرور برگردید. تغییر فقط به نگاشت پورت یک اپلیکیشن مربوط است. محدودکردن پورت به آدرس محلی، جای ورود امن، TLS یا کنترل دسترسی کاربران خود سرور را نمی‌گیرد.

مقدارهای واقعی را جای نمونه‌ها بگذارید

تنظیمات ابتدای آموزش را باز کنید، آدرس و نام سرویس خودتان را بنویسید و دکمهٔ اعمال را بزنید. رمز، توکن و کلید خصوصی وارد نکنید. مقدارها فقط برای همین آموزش، زبان و سیستم‌عامل در همین تب مرورگر نگه داشته می‌شوند و به سرور فرستاده نمی‌شوند. IP پیش‌فرض متعلق به محدودهٔ نمونه‌های مستندات است.

سرویس باید روی پورت داخلی انتخاب‌شده، HTTP بدون TLS ارائه کند. شمارهٔ پورت میزبان و کانتینر را مطابق وضعیت فعلی وارد کنید؛ در این راهنما شمارهٔ آن‌ها را عوض نمی‌کنیم. پورت تونل SSH جداست و باید روی کامپیوتر خودتان آزاد باشد.

01

قدم بعدی

نسخهٔ Docker و پروژهٔ درست را پیدا کنید

این دستورها را روی سرور Docker و با حساب مسئول استقرار اجرا کنید. نسخهٔ سرور باید ۲۸ یا جدیدتر باشد و در SecurityOptions نشانه‌ای از rootless نبینید. اگر فایل override یا متغیر اختصاصی Compose وجود دارد، ادامه ندهید تا روش اصلی استقرار مشخص شود.

bash

میزبان Docker

cd '/srv/myapp' || exit 1
sudo docker version --format '{{.Server.Version}}'
sudo docker info --format '{{json .SecurityOptions}}'
sudo docker compose version
test -f compose.yaml || exit 1
find . -maxdepth 1 -type f \( -name '*compose*.yml' -o -name '*compose*.yaml' \) -print
printenv | sort | sed -n '/^COMPOSE_/p'
sudo docker compose -f compose.yaml config --services
sudo docker compose -f compose.yaml ps
از کجا بدانم درست انجام شد؟

پروژه و سرویس درست مشخص شده‌اند؛ نسخهٔ Docker و نوع شبکه هم با پیش‌نیازهای آموزش مطابقت دارند.

02

قدم بعدی

ببینید کانتینر واقعاً روی کدام آدرس‌ها پورت باز کرده است

روی سرور، فقط اطلاعات لازم را از کانتینر بخوانید. خروجی کامل inspect ممکن است رمز یا توکن موجود در متغیرهای محیطی را نشان بدهد. شبکه‌های متصل، نوع درایور و گزینه‌های gateway را هم بررسی کنید؛ مراحل بعدی فقط برای bridge با NAT معمول مناسب‌اند.

پرس‌وجوی RPM فقط وجود ابزارها را بررسی می‌کند. اگر بسته‌ای کم است، آن را از روال مجاز DNF سرور تأمین کنید. zoneهای فعال firewalld را بدون تغییر بخوانید. اگر firewalld غیرفعال است یا zone مربوط به Docker وجود ندارد، همین وضعیت را ثبت و بک‌اند واقعی فایروال را بررسی کنید؛ برای رفع اشکال، سرویس را خودسرانه فعال نکنید.

bash

میزبان Docker

cd '/srv/myapp' || exit 1
cid=$(sudo docker compose -f compose.yaml ps -q 'web')
test -n "$cid" || exit 1
sudo docker inspect "$cid" --format '{{json .HostConfig.NetworkMode}}'
sudo docker inspect "$cid" --format '{{json .NetworkSettings.Ports}}'
sudo docker port "$cid"
for net in $(sudo docker inspect "$cid" --format '{{range $name, $value := .NetworkSettings.Networks}}{{$name}} {{end}}'); do
  sudo docker network inspect "$net" --format '{{.Name}} {{.Driver}} {{json .Options}}'
done
rpm -q curl python3 nano openssh-clients coreutils iproute firewalld
sudo firewall-cmd --state
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --get-zones
خروجی نمونه
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080
از کجا بدانم درست انجام شد؟

نگاشت فعلی Docker، ابزارهای نصب‌شده و وضعیت واقعی firewalld مشخص شده‌اند. خروجی نمونهٔ نگاشت عمومی، به‌تنهایی دسترسی از اینترنت را ثابت نمی‌کند.

03

قدم بعدی

ابتدا مطمئن شوید اپلیکیشن روی خود سرور پاسخ می‌دهد

روی خود سرور، یک درخواست بدون رمز یا توکن بفرستید. هر کد HTTP، حتی ۴۰۱ یا ۴۰۳، نشان می‌دهد سرویسی پاسخ داده است. در این بررسی از HTTP بدون TLS استفاده می‌کنیم؛ بنابراین اطلاعات ورود اپلیکیشن را همراه درخواست نفرستید.

bash

میزبان Docker

curl --noproxy '*' --connect-timeout 3 --max-time 5 -sS -o /dev/null -w 'HTTP %{http_code}\n' 'http://127.0.0.1:8080/'
از کجا بدانم درست انجام شد؟

اپلیکیشن روی خود سرور پاسخ HTTP می‌دهد. اگر اتصال برقرار نمی‌شود، پیش از تغییر پورت، مشکل اپلیکیشن را برطرف کنید.

همهٔ آموزش‌های آکادمی ↗