Portlar — -p, konteynerga brauzerdan kirish

~10 daq · Docker · Konteynerlar bilan ishlash

Muammodan boshlaylik

docker run -d --name api node-api

Konteyner ishlayapti, loglarda "Server 3000-portda ishga tushdi". Brauzerda http://localhost:3000 — "Ulanib bo'lmadi". Ilova ishlayapti, lekin unga yetib bo'lmaydi.

Yoki teskari muammo: ikki loyihada ham PostgreSQL 5432-portda — ikkinchisi ishga tushmaydi: "port is already allocated".


Port qanday ishlaydi

Konteynerning o'z tarmog'i bor (3-dars). Uning portlari — ichki. Tashqaridan kirish uchun port ulash (port mapping, publishing) kerak:

Brauzer → localhost:8080 ─────→ [ Docker ] ─────→ konteyner:80 → Nginx
          (host porti)                            (konteyner porti)
docker run -d -p 8080:80 nginx
#                ↑    ↑
#              HOST  KONTEYNER

Tartib: host:konteyner — chap tomon — sizning kompyuteringiz, o'ng tomon — konteyner ichi. Eng ko'p adashtiriladigan joy.


Variantlar

-p 8080:80              # host 8080 → konteyner 80
-p 80:80                # bir xil port
-p 3000:3000
-p 127.0.0.1:5432:5432  # FAQAT shu kompyuterdan kirish mumkin
-p 5432                 # host porti tasodifiy tanlanadi
-p 8080:80 -p 8443:443  # bir nechta port
-p 5000-5010:5000-5010  # diapazon
-p 53:53/udp            # UDP

Tasodifiy port qaysi biri ekanini bilish:

docker port mening-konteyner
# 5432/tcp -> 0.0.0.0:55012

Bir xil xizmat — turli portlarda

Ikki loyiha, ikkala ham PostgreSQL:

docker run -d --name pg-dokon  -e POSTGRES_PASSWORD=x -p 5432:5432 postgres:17
docker run -d --name pg-blog   -e POSTGRES_PASSWORD=x -p 5433:5432 postgres:17
docker run -d --name pg-eski   -e POSTGRES_PASSWORD=x -p 5434:5432 postgres:13

Konteyner ichida uchalasi ham 5432 da ishlaydi. Tashqarida — 5432, 5433, 5434. Hatto turli versiyalar — bir vaqtda, to'qnashuvsiz. Kompyuterga o'rnatilgan bazalar bilan bu deyarli imkonsiz.

Ulanish: localhost:5433 → blog bazasi.


Xavfsizlik: 0.0.0.0 va 127.0.0.1

-p 5432:5432

Standart holatda port barcha tarmoq interfeyslarida ochiladi (0.0.0.0) — ya'ni nafaqat kompyuteringizdan, balki tarmoqdagi boshqa qurilmalardan ham. Kafe Wi-Fi sida — boshqa mijozlar sizning bazangizga ulanishga urinishi mumkin. Serverda — butun internet.

-p 127.0.0.1:5432:5432

Faqat lokal kirish. Baza, Redis, admin panellar uchun — doim shunday.

[!WARNING] Linux serverda Docker o'z port qoidalarini iptables ga to'g'ridan-to'g'ri yozadi va UFW firewall ni chetlab o'tadi. ufw deny 5432 yozdingiz, lekin -p 5432:5432 bilan ishlayotgan konteyner baribir internetga ochiq. Bu ko'p uchraydigan va xavfli xato — minglab MongoDB va Redis bazalari aynan shu sababli o'g'irlangan. Serverda: bazalarni -p siz (faqat Docker tarmog'i ichida, 24-dars) yoki 127.0.0.1: bilan.


Ichki va tashqi portlar

Har bir xizmatni tashqariga ochish shart emas:

Internet → [80/443] Nginx ─→ [3000] API ─→ [5432] PostgreSQL
            ochiq           ichki          ichki

Faqat Nginx ga -p 80:80 -p 443:443. API va baza — tashqi portsiz; ular bir-biri bilan Docker tarmog'i orqali gaplashadi (24-dars). Har bir ochiq port — potentsial hujum nuqtasi.


EXPOSE

Dockerfile larda (va docker ps da) uchraydi:

EXPOSE 3000

Bu — faqat hujjat: "bu image 3000-portni tinglaydi". Hech narsani ochmaydi. Ochish — faqat -p bilan. (docker run -P — barcha EXPOSE qilingan portlarni tasodifiy host portlariga ulaydi.)


Tez-tez uchraydigan muammolar

port is already allocated — host porti band: boshqa konteyner yoki kompyuterdagi dastur (o'rnatilgan MySQL). Boshqa host porti tanlang yoki bandini toping:

docker ps --filter "publish=5432"

Ilova konteynerda ishlayapti, lekin ulanib bo'lmayapti — ilova localhost / 127.0.0.1 ni tinglayapti. Konteyner ichidagi localhost — faqat konteynerning o'zi! Ilova 0.0.0.0 ni tinglashi kerak:

app.listen(3000, '0.0.0.0');        // ✅ Express
// Vite: vite --host 0.0.0.0
// Next.js: next dev -H 0.0.0.0
// Django: python manage.py runserver 0.0.0.0:8000

Bu — boshidagi muammoning eng ko'p uchraydigan sababi.


Nima uchun shunday?

Nima uchun konteyner ichidagi localhost tashqaridan ko'rinmaydi?

Har bir konteynerning o'z tarmoq nomlar maydoni (network namespace) bor — o'z tarmoq interfeyslari, o'z localhost i. Ilova 127.0.0.1 ni tinglasa — u faqat konteyner ichidagi so'rovlarni qabul qiladi. Docker esa tashqaridan kelgan so'rovni konteynerning tashqi interfeysiga yo'naltiradi — 127.0.0.1 ga emas. 0.0.0.0 — "barcha interfeyslar" — ilova har qanday yo'ldan kelgan so'rovni qabul qiladi. Izolyatsiya — xavfsizlik uchun; 0.0.0.0 — ataylab ochish.


Xulosa

Eslab qoling:

  • -p HOST:KONTEYNER — chap — kompyuter, o'ng — konteyner
  • Turli host portlari — bir xil xizmatning ko'p nusxasi
  • 127.0.0.1:host:konteyner — faqat lokal; bazalar uchun doim
  • Linux serverda Docker UFW ni chetlab o'tadi — bazalarni ochmang
  • Faqat kerakli xizmatni tashqariga oching (Nginx); qolganlari — ichki tarmoqda
  • EXPOSE — faqat hujjat
  • Ilova 0.0.0.0 ni tinglasin, localhost ni emas

Keyingi dars

10-dars: Muhit o'zgaruvchilari — -e, --env-file