連不上容器的四個原因與 -p 的方向
「容器明明跑起來了,瀏覽器卻連不上」是初學第一名的卡關點。因為 network namespace 的關係,容器的 port 80 跟主機的 port 80 是兩個完全不同的東西。
(port 指的是 TCP port,就是平常講的 80 port、443 port——同一個 IP 上用來區分不同服務的號碼。容器有自己的 network namespace,等於有自己一整套 port 空間。)
口訣:-p 主機:容器
左邊自由選,右邊必須是容器裡程式真的在聽的 port(由 image 決定)。
docker run -d -p 8080:80 --name web nginx:1.25-alpine
docker port web # 查某個容器的 port 對應照順序檢查
- 忘了加
-p—docker ps的 PORTS 欄要有0.0.0.0:8080->80/tcp這種帶箭頭的字樣,沒箭頭就是沒轉發 - 右邊那個 port 寫錯 — 寫
-p 8080:8080但 nginx 聽的是 80。查法:Docker Hub 說明或docker inspect看ExposedPorts - 主機 port 被佔用 —
bind: address already in use,用lsof -i :8080找佔用者 - 容器裡的程式只聽 127.0.0.1 — 最陰險的一種。
app.listen(3000, '127.0.0.1')只接受容器內部連線,外面轉發進來的封包被拒。容器裡的服務一定要聽0.0.0.0
EXPOSE 不會開 port
Dockerfile 的 EXPOSE 3000 只是文件,宣告給讀的人和工具看,要真的連得到還是得 -p(唯一例外是 docker run -P 大寫,自動把所有 EXPOSE 的 port 隨機對應到主機)。
⚠️ 容器之間互連不需要 -p → 容器之間要用容器名稱連線而不是 localhost。