4.2 容器間的通訊網路#
一個常見的困境#
你用容器跑了一個後端和一個資料庫,後端要連資料庫。第一個直覺是「用 2.3 節的埠對映,連 localhost:5432」——但在容器內,localhost 指的是容器自己,不是主機。這條路不通(或不乾淨)。
正確的解法是 Docker 網路:把多個容器放進同一個自訂網路,它們就能用容器名稱互相訪問。
兩種網路的區別#
預設 bridge 網路#
不特別設定時,所有容器都在 Docker 的預設 bridge 網路——但預設網路上容器之間不能用名稱互訪,只能靠 IP(IP 會變,不可靠)。
自訂網路(建議)#
自建的網路自帶 DNS 服務:容器名稱就是主機名稱,直接可連。
# 建立自訂網路
docker network create my-net
# 把後端與資料庫放進同一個網路
docker run -d --name db --network my-net \
-v pgdata:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=mysecret \
postgres
docker run -d --name api --network my-net -p 8000:8000 my-app:v1
之後在 api 容器內,連線字串直接寫容器名稱:
# 在 api 容器內(或其他同網路容器內):
psql -h db -U postgres # ← host 就寫 db,不用 IP、不用 localhost
flowchart LR
subgraph my-net[自訂網路 my-net]
API[api 容器] -->|"主機名稱 = db"| DB[(db 容器<br/>postgres)]
API --> CACHE[cache 容器<br/>redis]
end
主機用戶 -.->|-p 8000:8000| API容器間通訊不佔用主機埠——只有需要被外部(瀏覽器、使用者)訪問的容器才需要 -p。資料庫不該暴露給外部,所以不給它 -p,這同時也是安全設計。
網路管理常用指令#
docker network create my-net # 建立
docker network ls # 列出
docker network inspect my-net # 看網路內有哪些容器
docker network connect my-net web # 把執行中的容器加入網路
docker network rm my-net # 刪除
實戰:後端 + Redis + PostgreSQL#
docker network create app-net
docker run -d --name cache --network app-net redis
docker run -d --name db --network app-net \
-v pgdata:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=mysecret postgres
docker run -d --name api --network app-net -p 8000:8000 my-app:v1
連線設定的工程意義:
api→ 資料庫:host=db, port=5432api→ Redis:host=cache, port=6379- 這些主機名稱在任何環境都一樣——開發、測試、正式環境的設定可以完全一致
本章小結#
- 容器內的
localhost是容器自己,不是主機 - 自訂網路自帶 DNS:容器名稱就是主機名稱——
docker network create - 只有需要外部訪問的容器才加
-p;資料庫不暴露,更安全 - 容器間通訊不佔主機埠
- 用容器名稱連線,各環境設定一致
想一想#
- 為什麼在容器內連
localhost:5432連不到另一個容器裡的資料庫? - 為什麼資料庫容器「不該」加
-p 5432:5432?什麼情況下才需要? - 「用容器名稱當主機名稱」對多環境部署有什麼好處?