跳轉到

2.3 網路連接與埠對映#

容器是隔離的:連網路也隔離#

容器有自己的網路空間——容器內監聽 80 埠,主機上沒有人能直接連到它。要讓外部(你的瀏覽器、其他程式)連到容器內的服務,就要做埠對映(port mapping):把主機的某個埠轉發到容器的埠。

-p:埠對映#

docker run -d -p 8080:80 nginx
#        ↑   └─┬─┘
#      背景執行  主機 8080 埠 → 容器 80 埠

語法:-p <主機埠>:<容器埠>。之後在瀏覽器打開 http://localhost:8080,就會看到 Nginx 的歡迎頁。

幾個實用的變化:

-p 8080:80        # 主機 8080 → 容器 80(最常用)
-p 127.0.0.1:8080:80   # 只允許本機連(不對外暴露,更安全)
-p 8080           # 只指定主機埠,容器埠隨機分配(少用)

初學者常見困惑:「為什麼瀏覽器連不上?」依序檢查:(1) 有沒有加 -p?(2) 埠號寫對了嗎(左邊是主機埠)?(3) 主機埠有沒有被其他程式佔用(錯誤訊息會說 port is already allocated)?

查看埠對映#

docker ps                 # PORTS 欄位顯示 0.0.0.0:8080->80/tcp
docker port my-nginx      # 直接列出某容器的對映

實戰:一秒啟動 Nginx / Redis / PostgreSQL#

有了埠對映,任何主流服務都能一行指令啟動,不用在本機安裝任何東西:

# Nginx 網頁伺服器:http://localhost:8080
docker run -d -p 8080:80 --name web nginx

# Redis 快取:主機 6379 埠
docker run -d -p 6379:6379 --name cache redis

# PostgreSQL 資料庫:需要環境變數設密碼
docker run -d -p 5432:5432 --name db \
  -e POSTGRES_PASSWORD=mysecret \
  postgres

測試一下:

# 測 Redis
docker exec -it cache redis-cli ping
# PONG

# 測 PostgreSQL
docker exec -it db psql -U postgres -c "SELECT version();"

這就是容器最香的用法:本機不用裝 Redis、PostgreSQL、Nginx,需要時一行指令啟動、用完 docker rm -f 刪除,主機乾乾淨淨。

埠衝突:同一個服務跑多個#

埠對映讓你可以把同一個 Image 的多個實例映射到不同主機埠:

docker run -d -p 8081:80 --name web1 nginx
docker run -d -p 8082:80 --name web2 nginx
# localhost:8081 和 localhost:8082 各是一個獨立的 Nginx

但注意:容器之間若要互相訪問,不該靠埠對映,而該用 Docker 網路(見 4.2 節)。

本章小結#

  • 容器網路是隔離的,-p 主機埠:容器埠 做埠轉發
  • 連不上依序檢查:有無 -p、埠號順序、埠是否被佔用
  • 一行指令啟動 Nginx/Redis/PostgreSQL,本機零安裝
  • 同一 Image 可映射到不同主機埠跑多個實例
  • 容器間通訊用 Docker 網路,不靠埠對映(第四章)

想一想#

  1. docker run -d -p 8080:80 nginx 中,兩個 80 各代表什麼?瀏覽器該連哪個埠?
  2. 想在本機同時測試「新舊兩個版本的後端」,埠該怎麼映射?
  3. 為什麼 -p 127.0.0.1:8080:80 比 -p 8080:80 更安全?