告別 localhost:3000 — 反向代理完全上手指南
告別 localhost:3000 — 反向代理完全上手指南

localhost:3000 是前端、localhost:8080 是 API、localhost:5432 是資料庫管理介面、localhost:9000 是另一個微服務... 我甚至得開一個備忘錄記錄哪個 port 是什麼服務,不然隔天醒來完全想不起來。
更慘的是,當我想測試一個需要 HTTPS 的功能時,瀏覽器跳出那個刺眼的「您的連線不安全」警告,點了好幾次「繼續前往」才能看到畫面。這種開發體驗,說實話,真的很差。
反向代理:你的網站需要一個「前台」
怎麼說呢,你可以把反向代理想像成公司的前台。
想像一下:如果一間公司沒有前台,訪客直接闖進辦公區找人會發生什麼事?有人找工程部、有人找業務部、有人其實是來推銷的、有人根本走錯棟...整個辦公室會亂成一團。
所以公司會設一個前台。訪客先到前台,說明來意,前台確認身份後再引導到正確的部門。推銷員?直接擋掉。可疑人物?通報保全。

反向代理做的就是這件事,只是場景換成了網路世界。
所有來自網路的請求,不會直接打到你的後端伺服器,而是先經過反向代理這個「前台」。反向代理會檢查請求、決定要轉發給哪個服務、處理一些雜事(像是 SSL 加解密),然後把回應送回給使用者。
你的後端服務們呢?它們只需要專心做自己的事,不用煩惱外面的世界有多混亂。
正向 vs 反向,三秒區分
這兩個詞很容易搞混,我用一個簡單的方式區分:
正向代理:幫「你」出去拿東西。你不想讓外面知道你是誰,所以派一個代理人出去。VPN 就是這個概念。
反向代理:幫「伺服器」接待客人。外面的人不知道裡面有幾台伺服器、長什麼樣子,只看到一個統一的入口。
一句話記住:正向保護客戶端,反向保護伺服器。
它能幫你做什麼?
好,概念懂了,但反向代理到底能解決什麼問題?
統一入口,告別 port 地獄
這是我當初最有感的一點。有了反向代理,你可以這樣設定:
myapp.local→ 前端服務api.myapp.local→ API 服務admin.myapp.local→ 管理後台
全部走 443 port,全部用漂亮的網址,再也不用記那些該死的 port 號。
自動 HTTPS,一勞永逸
現在很多功能都需要 HTTPS 才能用:地理定位、相機存取、Service Worker... 在本地開發環境搞 HTTPS 以前是件很痛苦的事,要自己生憑證、設定信任、每次都要點「繼續前往不安全的網站」。
但有些反向代理工具(像 Caddy)可以自動幫你處理 SSL 憑證。在生產環境它會自動向 Let's Encrypt 申請免費憑證,在本地開發則可以搭配 mkcert 產生被系統信任的憑證。
負載均衡
當你的服務開始有流量,一台伺服器撐不住的時候,反向代理可以幫你把請求分散到多台伺服器。這就是所謂的負載均衡。
┌─ Server 1
使用者 → 反向代理 ──┼─ Server 2
└─ Server 3
反向代理會用各種演算法(輪詢、最少連線、IP Hash)來決定要把請求送到哪台伺服器。
安全防護
因為外部請求不會直接接觸到後端伺服器,所以:
- 後端伺服器的真實 IP 被隱藏
- 可以在反向代理層做速率限制,擋掉惡意請求
- 可以設定 WAF(Web Application Firewall)過濾攻擊
- DDoS 攻擊打到的是反向代理,不是你的應用伺服器
快取加速
反向代理可以快取靜態資源(圖片、CSS、JS),這樣重複的請求就不用每次都打到後端,大幅減少伺服器負擔。
四大天王,怎麼選?

市面上反向代理的選擇很多,但最常被拿出來討論的就是這四個:Nginx、Caddy、Traefik、HAProxy。
我花了不少時間研究和實測,簡單分享一下心得。
Nginx:穩如老狗的老將
Nginx 大概是最多人用的反向代理,從 2004 年就存在了。效能極強、資源消耗低、文件和社群資源超級豐富。
但說實話,它的設定檔對新手不太友善。光是要設定一個基本的反向代理,就要寫這麼一大段:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
如果你追求極致效能、需要非常細緻的控制,或是你已經很熟悉 Nginx,那它絕對是好選擇。
Caddy:簡單到不可思議的新星
Caddy 是這幾年竄起來的新選擇,主打「簡單」和「自動 HTTPS」。
同樣的功能,Caddy 的設定長這樣:
example.com {
reverse_proxy localhost:3000
}
沒了。就這三行。
HTTPS 憑證?它會自動幫你處理。HTTP 轉 HTTPS?預設就會。
我第一次用 Caddy 的時候真的有點驚訝,怎麼可以這麼簡單?效能雖然比 Nginx 稍微差一點,但對大多數應用來說根本感覺不出來。
如果你是新手,或是你只是想快速把事情搞定,Caddy 是我最推薦的選擇。
Traefik:為容器而生
如果你的服務都跑在 Docker 或 Kubernetes 上,Traefik 會讓你很驚豔。
它可以自動偵測 Docker 容器的啟動和關閉,不用手動改設定檔。你只要在 docker-compose.yml 裡加幾個 label,Traefik 就會自動幫你設定好路由。
services:
myapp:
image: myapp
labels:
- "traefik.enable=true"
- "traefik.http.routers.myapp.rule=Host(`myapp.local`)"
缺點是學習曲線比較陡,概念也比較多(providers、routers、middlewares...),效能也是四個裡面最差的。但在容器環境裡,那個自動化的體驗真的很香。
HAProxy:負載均衡之王
HAProxy 專注在負載均衡這件事上,做到極致。很多大公司的高流量系統都用它。
但它不是 web server,沒有內建快取功能,設定也相對複雜。如果你的場景主要是「把流量分散到很多台伺服器」,HAProxy 是專業選擇。一般使用的話,Nginx 或 Caddy 就夠了。
所以到底怎麼選?
| 你的情況 | 推薦 |
|---|---|
| 新手、想快速上手 | Caddy |
| 追求極致效能 | Nginx |
| Docker/Kubernetes 環境 | Traefik |
| 大規模負載均衡 | HAProxy |
| 不知道選什麼 | Caddy |
動手做:5 分鐘搞定本地開發環境
說了這麼多,來實際操作一下。我會用最簡單的方式,讓你在本地開發環境用上 HTTPS 和自訂域名。
第一步:安裝 mkcert
mkcert 是一個工具,可以產生被本機系統信任的 SSL 憑證。
# macOS
brew install mkcert nss
# 安裝本地 CA(只需要執行一次)
mkcert -install
第二步:產生憑證
# 在你的專案目錄下
mkdir certs && cd certs
mkcert myapp.local "*.myapp.local"
這會產生兩個檔案:myapp.local+1.pem(憑證)和 myapp.local+1-key.pem(私鑰)。
第三步:設定 hosts 檔案
# 編輯 /etc/hosts(需要 sudo)
sudo nano /etc/hosts
# 加入這行
127.0.0.1 myapp.local api.myapp.local
第四步:建立 Caddyfile
myapp.local {
tls ./certs/myapp.local+1.pem ./certs/myapp.local+1-key.pem
reverse_proxy localhost:3000
}
api.myapp.local {
tls ./certs/myapp.local+1.pem ./certs/myapp.local+1-key.pem
reverse_proxy localhost:8080
}
第五步:啟動 Caddy
# 安裝 Caddy(如果還沒裝)
brew install caddy
# 啟動
caddy run
完成。現在打開瀏覽器,輸入 https://myapp.local,你會看到漂亮的綠色鎖頭,連到你的前端服務。
如果你用 Docker Compose,可以把 Caddy 也容器化,整個開發環境一個 docker-compose up 就搞定。
下一步
反向代理這個概念其實不複雜,但它能解決的問題比你想像的多。
從今天開始,試著在你的下一個專案用上它。不一定要用在生產環境,光是本地開發就能讓你的體驗好上很多。
當你開始習慣 https://myapp.local 這種開發方式,你就回不去了。
至於更進階的主題——雲端部署、安全配置、Kubernetes Ingress——那就是另一個故事了。
先把基礎打好,其他的慢慢來。
延伸閱讀
- Caddy 官方文件 - 深入了解 Caddy 的所有功能
- Nginx 官方文件 - Nginx 完整參考
如果這篇文章對你有幫助,歡迎分享給同樣在跟 port 地獄奮戰的朋友。
本文最初發布於 HackMD @BASHCAT。
留言
張貼留言