iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
IT Operation

從前後端踏上 AWS 雲端架構勇者之路系列 第 25 篇

網域與 Nginx:網址怎麼找到 EC2 裡的 Container?

  • 分享至 

  • xImage
  •  

上一段已經讓 EC2 裡的 Node.js 連到 RDS,現在要把使用者連進來的這一段接好

假設你把 http://127.0.0.1:8080/health 傳給同事,他能打開嗎?對他的電腦來說,127.0.0.1 是他自己,根本不是你的 EC2 啊 XD

今天會用到兩個東西:DNS 把網域名稱查成 IP,Nginx 接收請求,再轉給 Container

瀏覽器先向 DNS 查 IP,再連到 EC2 的 Nginx,由 Nginx 轉給同機 Container

先啟動前篇的 EC2 與容器。在 EC2 執行 curl http://127.0.0.1:8080/health,應該能看到 {"status":"ok"}

先固定 IP,再幫它取名字

這次先用 Elastic IP(EIP),把對外的 IP 固定下來

回 AWS 網頁,區域切到東京,進入 VPC → Elastic IPs → Allocate Elastic IP address:

  1. Public IPv4 address pool 保留 Amazon's pool of IPv4 addresses。
  2. Network border group 確認是 ap-northeast-1,按 Allocate。
  3. 回清單選這個 EIP,點 Actions → Associate Elastic IP address。
  4. Resource type 選 Instance,選執行 API 的 EC2;Private IP address 選那台主機的主要私有 IP,按 Associate。

AWS Console 實拍:Elastic IP 配置表單,選 Amazon 的 IPv4 pool 與東京 ap-northeast-1

上圖是配置前的欄位。你做完關聯後,再回 EC2 → Instances → 選主機,確認 Elastic IP addresses 顯示剛才的 IP,後面的 SSH 和 DNS 都改用它

關聯 EIP 後,原本自動配發的公有 IP 會被釋放,舊的 SSH 連線也可能中斷。這時用新 EIP 重新登入就好,附上文件(AWS:關聯 Elastic IP)

也提醒下,EIP 保留在帳號裡就有公有 IPv4 費用,EC2 停機也不會讓這筆費用消失。這次會留到下一篇練習 HTTPS,做完不再使用時才釋放

DNS 要填在哪裡?

有自己的網域,就到管理這個網域的 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

Nginx 要裝在哪裡?

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 不加對外規則

告訴 Nginx,要轉去哪一個 port

在 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 送到哪裡

Nginx 的 listen、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 測 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


上一篇
Container 跑起來了,為什麼還連不到私有 RDS?
下一篇
HTTPS:有網址之後,還要替連線加密
系列文
從前後端踏上 AWS 雲端架構勇者之路 共 26 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言