容器之間要用容器名稱連線而不是 localhost

App 容器要連 DB 容器,host 填 localhost 是錯的——初學第二名的卡關點。每個容器有自己的 network namespace,App 容器裡的 localhost 指的是「App 容器自己」,所以只會拿到 ECONNREFUSED

正確做法

docker network create app-net                     # 1. 建自訂網路
 
docker run -d --name postgres --network app-net \
  -e POSTGRES_PASSWORD=dev123 postgres:16-alpine  # 2. DB 加入
 
docker run -d --name api --network app-net -p 3000:3000 \
  -e DB_HOST=postgres -e DB_PORT=5432 my-app:1.0  # 3. App 加入,host 填容器名稱

三個重點

  1. 用自訂 network — 只有自訂 network 才有容器名稱的 DNS 解析,預設 bridge 沒有
  2. 連線位址填容器名稱postgres),不是 localhost、不是 IP(IP 會變)
  3. port 填容器內部原始 port(5432),不是 -p 映射到主機的那個——容器之間的通訊根本不經過主機,跟 -p 無關

安全紅利

-p 只在「從容器外面連進去」時才需要。所以正式環境常見做法是:只有對外的 API / nginx 容器開 -p,資料庫容器完全不開——資料庫從外網根本連不到。

除錯

docker exec -it api shping postgresnc -zv postgres 5432:ping 不到=不在同一個網路;ping 得到但連不上=對方服務還沒起來或 port 錯。

網路模式:bridge(預設,99% 用這個)/host(不隔離,-p 失效,Mac 支援有限)/noneoverlay(跨主機叢集)。