9.5 外部訪問容器

容器執行在自己的隔離網路環境中 (通常是 Bridge 模式)。為了讓外部網路訪問容器內的服務,我們需要將容器的連接埠對映到宿主機的連接埠。

9.5.1 為什麼要對映連接埠

容器的網路訪問規則如下:

  • 容器之間:可以透過 IP 或容器名 (自定義網路) 互通。
  • 宿主機訪問容器:原生 Linux 環境下可按網路設定訪問容器 IP;Docker Desktop 上不能依賴容器 IP,應透過連接埠對映、容器名(容器間)或 host.docker.internal 等機制訪問。
  • 外部網路訪問容器:❌ 預設無法直接訪問。

為了讓外部 (如你的瀏覽器、其他區域網路機器) 訪問容器內的服務,我們需要將容器的連接埠 對映 到宿主機的連接埠。

flowchart TD User["外部使用者 (Browser)"] --> Host["宿主機 (localhost:8080)"] Host --> Proxy["Docker Proxy
連接埠對映 (8080 -> 80)"] Proxy --> Container["容器 (Class B: 80)"]

9.5.2 連接埠對映方式

Docker 提供了多種方式來指定連接埠對映。

1. 指定對映

使用 -p <宿主機連接埠>:<容器連接埠> 格式:

## 將宿主機的 8080 連接埠對映到容器的 80 連接埠

$ docker run -d -p 8080:80 nginx

此時訪問 http://localhost:8080 即可看到 Nginx 頁面。

多種格式

格式 含義 範例
ip:hostPort:containerPort 繫結指定 IP 的特定連接埠 -p 127.0.0.1:8080:80 (僅 IPv4 本機訪問)
ip::containerPort 繫結指定 IP 的隨機連接埠 -p 127.0.0.1::80
hostPort:containerPort 繫結所有地址(通常包括 0.0.0.0[::])的特定連接埠 -p 8080:80 (預設)
containerPort 繫結所有地址的隨機連接埠 -p 80

2. 隨機對映

如果不關心宿主機使用哪個連接埠,可以使用隨機對映。使用 -P (大寫) 引數,Docker 會把 Dockerfile 中 EXPOSE 指令暴露的所有連接埠發布到宿主機的隨機高位連接埠。具體落在哪個連接埠,取決於宿主機當前可用的臨時連接埠範圍。

$ docker run -d -P nginx

檢視對映結果:

$ docker ps
CONTAINER ID   PORTS
abc123456      0.0.0.0:49153->80/tcp

此時 Nginx 被對映到了宿主機的一個隨機高位連接埠,例如 49153


9.5.3 檢視連接埠對映

可以使用以下指令檢視容器的連接埠對映:

docker port

執行 docker port 可以檢視到指定容器的連接埠對映情況:

$ docker port mycontainer
80/tcp -> 0.0.0.0:8080
80/tcp -> [::]:8080

docker ps

執行 docker ps 可以檢視到所有容器的連接埠對映清單:

$ docker ps
CONTAINER ID   IMAGE     PORTS                  NAMES
abc123456      nginx     0.0.0.0:8080->80/tcp   web

9.5.4 最佳實踐與安全

在設定連接埠對映時,需要注意以下安全事項:

1. 限制監聽 IP

預設情況下,-p 8080:80 會監聽所有可用地址,常見輸出包括 0.0.0.0:8080[::]:8080。這意味著任何人只要能連線你的宿主機 IP,就能訪問該服務。

如果不希望對外暴露 (例如資料庫服務),應繫結到回環地址。IPv4 使用 127.0.0.1,IPv6 使用 [::1]

## 僅允許本機訪問

$ docker run -d -p 127.0.0.1:3306:3306 mysql
$ docker run -d -p '[::1]:3306:3306' mysql

2. 避免連接埠衝突

如果宿主機 8080 已經被佔用了,容器將無法啟動。

解決

  • 更換宿主機連接埠:-p 8081:80
  • 讓 Docker 自動分配:-p 80

3. UDP 對映

預設是 TCP 協定。如果要對映 UDP 服務 (如 DNS,Syslog):

$ docker run -d -p 53:53/udp dns-server

9.5.5 實現原理

Docker 使用 docker-proxy 程序 (使用者態) 或 iptables DNAT 規則 (核心態) 來實現連接埠轉發。

當流量到達宿主機連接埠時,iptables 規則將其目標地址修改為容器 IP 並轉發:

## 簡化的 iptables 邏輯

iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80

這也是為什麼你在容器內部看到的訪問來源 IP 通常是閘道器 IP (如 172.17.0.1),而不是真實的外部 Client IP (除非使用 host 網路模式)。


第 79 页,共 196 页
使用 mdPress 构建