---
# System prepended metadata

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

---


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

![reverse-proxy-cover](https://hackmd.io/_uploads/rJMXTqyvbe.jpg)


`localhost:3000` 是前端、`localhost:8080` 是 API、`localhost:5432` 是資料庫管理介面、`localhost:9000` 是另一個微服務... 我甚至得開一個備忘錄記錄哪個 port 是什麼服務，不然隔天醒來完全想不起來。

更慘的是，當我想測試一個需要 HTTPS 的功能時，瀏覽器跳出那個刺眼的「您的連線不安全」警告，點了好幾次「繼續前往」才能看到畫面。這種開發體驗，說實話，真的很差。


---

## 反向代理：你的網站需要一個「前台」

怎麼說呢，你可以把反向代理想像成公司的前台。

想像一下：如果一間公司沒有前台，訪客直接闖進辦公區找人會發生什麼事？有人找工程部、有人找業務部、有人其實是來推銷的、有人根本走錯棟...整個辦公室會亂成一團。

所以公司會設一個前台。訪客先到前台，說明來意，前台確認身份後再引導到正確的部門。推銷員？直接擋掉。可疑人物？通報保全。

![reverse-proxy-comparison](https://hackmd.io/_uploads/Hk2Ea91vZe.jpg)

反向代理做的就是這件事，只是場景換成了網路世界。

所有來自網路的請求，不會直接打到你的後端伺服器，而是先經過反向代理這個「前台」。反向代理會檢查請求、決定要轉發給哪個服務、處理一些雜事（像是 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），這樣重複的請求就不用每次都打到後端，大幅減少伺服器負擔。

---

## 四大天王，怎麼選？

![reverse-proxy-software](https://hackmd.io/_uploads/BJjHT9yv-e.jpg)

市面上反向代理的選擇很多，但最常被拿出來討論的就是這四個：Nginx、Caddy、Traefik、HAProxy。

我花了不少時間研究和實測，簡單分享一下心得。

### Nginx：穩如老狗的老將

Nginx 大概是最多人用的反向代理，從 2004 年就存在了。效能極強、資源消耗低、文件和社群資源超級豐富。

但說實話，它的設定檔對新手不太友善。光是要設定一個基本的反向代理，就要寫這麼一大段：

```nginx
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 就會自動幫你設定好路由。

```yaml
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 憑證。

```bash
# macOS
brew install mkcert nss

# 安裝本地 CA（只需要執行一次）
mkcert -install
```

### 第二步：產生憑證

```bash
# 在你的專案目錄下
mkdir certs && cd certs
mkcert myapp.local "*.myapp.local"
```

這會產生兩個檔案：`myapp.local+1.pem`（憑證）和 `myapp.local+1-key.pem`（私鑰）。

### 第三步：設定 hosts 檔案

```bash
# 編輯 /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

```bash
# 安裝 Caddy（如果還沒裝）
brew install caddy

# 啟動
caddy run
```

完成。現在打開瀏覽器，輸入 `https://myapp.local`，你會看到漂亮的綠色鎖頭，連到你的前端服務。

如果你用 Docker Compose，可以把 Caddy 也容器化，整個開發環境一個 `docker-compose up` 就搞定。

---

## 下一步

反向代理這個概念其實不複雜，但它能解決的問題比你想像的多。

從今天開始，試著在你的下一個專案用上它。不一定要用在生產環境，光是本地開發就能讓你的體驗好上很多。

當你開始習慣 `https://myapp.local` 這種開發方式，你就回不去了。

至於更進階的主題——雲端部署、安全配置、Kubernetes Ingress——那就是另一個故事了。

先把基礎打好，其他的慢慢來。

---

## 延伸閱讀


- [Caddy 官方文件](https://caddyserver.com/docs/) - 深入了解 Caddy 的所有功能
- [Nginx 官方文件](https://nginx.org/en/docs/) - Nginx 完整參考

---

*如果這篇文章對你有幫助，歡迎分享給同樣在跟 port 地獄奮戰的朋友。*
