上一段已經讓 EC2 裡的 Node.js 連到 RDS,現在要把使用者連進來的這一段接好
假設你把 http://127.0.0.1:8080/health 傳給同事,他能打開嗎?對他的電腦來說,127.0.0.1 是他自己,根本不是你的 EC2 啊 XD
今天會用到兩個東西:DNS 把網域名稱查成 IP,Nginx 接收請求,再轉給 Container
先啟動前篇的 EC2 與容器。在 EC2 執行 curl http://127.0.0.1:8080/health,應該能看到 {"status":"ok"}
這次先用 Elastic IP(EIP),把對外的 IP 固定下來
回 AWS 網頁,區域切到東京,進入 VPC → Elastic IPs → Allocate Elastic IP address:
Amazon's pool of IPv4 addresses。ap-northeast-1,按 Allocate。上圖是配置前的欄位。你做完關聯後,再回 EC2 → Instances → 選主機,確認 Elastic IP addresses 顯示剛才的 IP,後面的 SSH 和 DNS 都改用它
關聯 EIP 後,原本自動配發的公有 IP 會被釋放,舊的 SSH 連線也可能中斷。這時用新 EIP 重新登入就好,附上文件(AWS:關聯 Elastic IP)
也提醒下,EIP 保留在帳號裡就有公有 IPv4 費用,EC2 停機也不會讓這筆費用消失。這次會留到下一篇練習 HTTPS,做完不再使用時才釋放
有自己的網域,就到管理這個網域的 DNS 後台。假設你有 my-site.tw,想讓 api.my-site.tw 連到 EC2,就新增一筆 A 紀錄,告訴 DNS「這個名稱對應哪個 IPv4」:
| 欄位 | 填寫內容 |
|---|---|
| Type/類型 | A |
| Name/Host | api,部分後台要求完整 api.my-site.tw |
| Value/內容 | 剛才關聯的 EIP |
| TTL | 保留預設值,這是 DNS 答案可以快取多久 |
如果使用 Cloudflare 等有代理功能的服務,這次先選 DNS only/僅 DNS,讓瀏覽器直接連 EC2
可以用 nip.io 這個服務。假設 EIP 是 203.0.113.10,就使用 203.0.113.10.nip.io;它會依名稱裡的 IP 回覆 DNS 查詢,不需要自己再去新增 A 紀錄(nip.io 的解析方式)
203.0.113.10 是本文舉例的 IP,實際要換成自己的 EIP。這是第三方提供的網域,練習可用,正式網站若需要自己管理名稱,就用自己的網域
上面兩種選一種即可。下面的 api.example.com 都要換成你選好的完整名稱,例如 api.my-site.tw 或 自己的EIP.nip.io;名稱前不要加 http://
在自己電腦先查一次,macOS 執行:
dig +short api.example.com A
Windows PowerShell 執行:
Resolve-DnsName api.example.com -Type A
查到自己的 EIP,再繼續設定 Nginx。剛修改還看到舊 IP,先確認 A 紀錄有存好;DNS 快取還沒到期時,也可能暫時查到舊答案
假如自己管理的這個名稱原本有 AAAA 紀錄(對應 IPv6),但還沒設定可用的 IPv6 入口,就先移除這筆未使用的紀錄,以免部分連線走到不通的 IPv6
DNS 找到主機了,但收到 HTTP 請求後,要交給誰?
我們把 Nginx 裝在 EC2 主機上,接收 80 port 的請求,再轉到同一台主機的 127.0.0.1:8080。這種替後面的程式接收、轉送請求的做法,這種作法叫做 反向代理
HTTP 預設使用 80,所以使用者連 http://自己的網域/health 就好,不用再加 :8080
Container 仍保留前篇的 127.0.0.1:8080:8080 設定。使用者先連 Nginx,Node.js 繼續處理 API,後面也會由 Nginx 負責 HTTPS
安裝軟體需要管理權限,這次用 ubuntu 登入。在自己電腦另開終端機,使用建立 EC2 時下載的那把私鑰:
ssh -i "/你的私鑰路徑/建立EC2時的金鑰.pem" ubuntu@自己的EIP
macOS、Windows 都要把路徑換成自己的私鑰完整路徑,IP 換成剛才的 EIP
以下指令都在 EC2 的 ubuntu 視窗執行,沿用前面的 Ubuntu 24.04:
sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx
裝好後,回 AWS → EC2 → Instances → 選這台主機 → Security,點進主機實際使用的 Web SG,再進 Inbound rules → Edit inbound rules:
| 設定 | 本次要保留的值 |
|---|---|
| Type/Port | HTTP/TCP 80 |
| Source | Anywhere-IPv4,0.0.0.0/0 |
已經有這條 HTTP 規則就沿用,不用再加一次。SSH 22 繼續只限自己的公有 IP,8080 不加對外規則
在 EC2 的 ubuntu 視窗新增設定檔:
sudo nano /etc/nginx/sites-available/demo-api
貼上以下內容,server_name 改成剛才選好的網域:
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
在 nano 按 Ctrl+O、Enter 儲存,Ctrl+X 離開。設定有點長,先抓圖上這三個位置:listen 聽哪個 port、server_name 處理哪個網域、proxy_pass 送到哪裡
假設 Container 的主機入口改成 8081,proxy_pass 就要跟著改,不能還往 8080 送
後面的 proxy_set_header 會把使用者連的網域、來源 IP,以及 HTTP 或 HTTPS 一起帶給 Node.js
這份設定沒有改寫路徑,所以使用者請求 /health,Node.js 收到的也會是 /health
接著讓 Nginx 載入設定。sites-available 放設定檔,sites-enabled 放要啟用的連結,ln -s 就是在建立這個連結:
sudo ln -s /etc/nginx/sites-available/demo-api /etc/nginx/sites-enabled/demo-api
sudo nginx -t
連結已存在就不用重建。nginx -t 就會顯示 syntax is ok 和 test is successful,確認沒有錯誤後才執行:
sudo systemctl reload nginx
reload 的話會重新讀取設定,不用為了改 Nginx 重建 Node.js Image
我會先測 Container,再測同機的 Nginx,最後才回自己電腦測網域
| 在哪裡測 | 指令 | 可以確認什麼? |
|---|---|---|
EC2 的 ubuntu 視窗 |
curl -i http://127.0.0.1:8080/health |
Container 的程式能回應 |
EC2 的 ubuntu 視窗 |
curl -i -H 'Host: api.example.com' http://127.0.0.1/health |
Nginx 選到這個網域的設定,並轉給 Container |
| 自己電腦 | curl -i http://api.example.com/health |
外部也能透過 DNS、EC2 公有入口連到程式 |
網域都換成自己的;最後一行在 Windows PowerShell 請用 curl.exe。第二行的 Host 是告訴 Nginx「這次要找哪個網域」,這樣可以先留在 EC2 裡測,不必等外面的連線
三次應該都回 HTTP 200,內容就會是:
{"status":"ok"}
如果結果不同,可以先這樣檢查看看:
| 看到什麼 | 先檢查哪裡 |
|---|---|
Welcome to nginx! |
是否用了自己的完整網域;server_name、啟用連結與 reload 是否完成 |
| HTTP 502 | Nginx 已收到請求,但沒拿到後端回應;先測表格第一行,再看容器與 8080 |
{"error":"not found"} |
有沒有加 /health?這支範例 API 沒有首頁,直接開 / 會回 404 |
| EC2 內兩次都成功,自己電腦卻連線逾時 | DNS 是否指向 EIP、Web SG 是否允許 80、Public Subnet 路由是否仍有 0.0.0.0/0 → IGW |
遇到 502,也可以在 EC2 執行 sudo tail -n 50 /var/log/nginx/error.log 看錯誤~
今天先用沒有帳密的 /health 測 HTTP。下一篇再加上 HTTPS 憑證與自動續期,讓瀏覽器到 Nginx 的這段連線也有加密
如果接著做下一篇,就保留 EIP 與這份設定。暫停練習時可以停止 EC2,但 EIP、EBS 還是會計費哩
也提醒如果沒有打算練習,記得解除 EIP 關聯並釋放,也移除自己網域指向它的 A 紀錄。使用 nip.io 就停止使用舊網址
希望本篇你會喜歡,我們下篇見勒 :D