Docker / Port mapping

Port mapping

Container нь тусгаарлагдсан орчинд ажиллана — container-ийн доторх port гаднаас харагдахгүй. Port mapping нь host машины port-ийг container-ийн port-тэй холбоно.

Port mapping гэж юу вэ?

код
Хэрэглэгч → localhost:8080 → [Docker] → container:3000
  • Host port (8080) — таны компьютерийн port, гаднаас хандах
  • Container port (3000) — container дотор аппликейшн сонсдог port

Хоёр нь нэг байх шаардлагагүй.

-p флаг — port mapping

bash
docker run -p HOST_PORT:CONTAINER_PORT image_name

Жишээнүүд:

bash
# Host 8080 → Container 3000
docker run -p 8080:3000 myapp

# Ижил port ашиглах
docker run -p 3000:3000 myapp

# localhost дээр 80 port
docker run -p 80:80 nginx

Ажиллуулсны дараа browser-т http://localhost:8080 нээхэд container-ийн 3000 port-д хандана.

EXPOSE заавар

Dockerfile-д EXPOSE нь container ямар port ашиглахыг баримтжуулна. Бодит port нээхгүй — зөвхөн мэдээлэл (documentation).

dockerfile
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000          # "Энэ container 3000 port ашиглана" гэсэн мэдэгдэл
CMD ["node", "index.js"]

EXPOSE байвал ч -p флаггүйгээр гаднаас хандах боломжгүй.

bash
# EXPOSE байвал ч хандах боломжгүй — port mapping хэрэгтэй
docker run myapp                     # ❌ localhost дээрх port нэмэгдэхгүй
docker run -p 3000:3000 myapp        # ✅ localhost:3000 хандах боломжтой

-P флаг — автоматаар port mapping

-P (том үсэг) флаг нь EXPOSE-д заасан port бүрд host-ийн санамсаргүй port оноодог:

bash
docker run -P nginx
bash
docker ps
# PORTS: 0.0.0.0:32768->80/tcp

Host-ийн 32768 port Container-ийн 80 port-тэй холбогдлоо.

Аль port онооснийг харах:

bash
docker port container_name
# 80/tcp -> 0.0.0.0:32768

Олон port mapping

Нэг container-д олон port mapping хэрэгтэй үед:

bash
# HTTP ба HTTPS
docker run -p 80:80 -p 443:443 nginx

# Аппликейшн ба debug port
docker run -p 3000:3000 -p 9229:9229 myapp

# Олон сервис
docker run -p 8080:8080 -p 8443:8443 -p 9090:9090 myservice

Dockerfile-д:

dockerfile
EXPOSE 80
EXPOSE 443
# Эсвэл нэг мөрд
EXPOSE 80 443

Тодорхой IP хаяг заах

Анхдагч байдлаар 0.0.0.0 — бүх сүлжээний интерфейсд сонсоно. Зөвхөн localhost-д:

bash
# Зөвхөн localhost (127.0.0.1)-аас хандах боломжтой
docker run -p 127.0.0.1:3000:3000 myapp

# Бүх интерфейсд (анхдагч)
docker run -p 0.0.0.0:3000:3000 myapp

Production-д аюулгүй байдлын үүднээс IP хаяг зааж өгөхийг зөвлөдөг.

UDP port

Анхдагч байдлаар TCP. UDP port mapping:

bash
docker run -p 53:53/udp dns-server
docker run -p 5000:5000/tcp -p 5000:5000/udp myapp

Практик жишээ

Nginx вэб сервер:

bash
docker run -d --name web -p 8080:80 nginx

http://localhost:8080 — Nginx-ийн welcome хуудас харагдана.

PostgreSQL өгөгдлийн сан:

bash
docker run -d \
  --name postgres \
  -p 5432:5432 \
  -e POSTGRES_PASSWORD=secret \
  postgres:16

localhost:5432 дээр PostgreSQL-д холбогдож болно.

Node.js debug горим:

bash
docker run -d \
  --name myapp-debug \
  -p 3000:3000 \
  -p 9229:9229 \
  myapp node --inspect=0.0.0.0:9229 index.js

Chrome DevTools-ийг chrome://inspect хаягаар нэгтгэж debug хийнэ.

Port эзэлсэн байвал яах вэ?

bash
docker run -p 3000:3000 myapp
# Error: Bind for 0.0.0.0:3000 failed: port is already allocated

Шийдэл 1 — өөр host port ашиглах:

bash
docker run -p 3001:3000 myapp

Шийдэл 2 — аль процесс ашиглаж байгааг олж зогсоох:

bash
# Linux/Mac
lsof -i :3000
kill -9 PID

# Windows
netstat -ano | findstr :3000
taskkill /PID xxxx /F

Container-ийн port харах

bash
# Нэг container-ийн port mapping
docker port my-nginx

# docker ps-д харуулах
docker ps --format "table {{.Names}}\t{{.Ports}}"
код
NAMES       PORTS
my-nginx    0.0.0.0:8080->80/tcp
postgres    0.0.0.0:5432->5432/tcp

Дараагийн хичээлд:

Volume ашиглан container-ийн өгөгдлийг хэрхэн хадгалах, bind mount-аар хөгжүүлэлт хийх талаар судална.