2026年8月23日 星期日

從零打造自己的 AWS 股票看盤網站:EC2 + Ubuntu + Docker + Nginx + Node.js + K 線

 

🚀 從零打造自己的 AWS 股票看盤網站:EC2 + Ubuntu + Docker + Nginx + Node.js + K 線

最近想自己做一個可以放在網路上使用的股票 Dashboard,所以乾脆從零開始架一台 AWS EC2,自己建立 Linux Server,再把 Docker、Nginx、Node.js 和股票 API 串起來。

最後做出來的東西包含:

  • 🇹🇼 台股即時股價
  • 🇺🇸 美股即時股價
  • 📈 股票 K 線
  • 🔍 股票查詢
  • ➕ 網頁新增股票
  • 🗑️ 網頁刪除股票
  • 📝 記事本
  • 🧮 計算機
  • 🔄 自動更新
  • 🌐 使用瀏覽器直接開啟
  • 🐳 Docker Container 化
  • 🔀 Nginx Reverse Proxy

而且整套不是架在自己的電腦,而是放在 AWS EC2 上。


一、先了解最後的架構

最後整個系統大概長這樣:

                    Internet
                       │
                       ▼
              ┌─────────────────┐
              │    AWS EC2      │
              │     Ubuntu      │
              └────────┬────────┘
                       │
                       ▼
              ┌─────────────────┐
              │     Nginx       │
              │      :80        │
              └────────┬────────┘
                       │
                       ▼
              ┌─────────────────┐
              │    Node.js      │
              │      :3000      │
              └────────┬────────┘
                       │
             ┌─────────┴─────────┐
             ▼                   ▼
       Yahoo Finance          新聞 API
          API                    API
             │
             ▼
       股票 / K線資料

使用者其實不需要知道 Node.js 的 3000 Port。

瀏覽器只需要:

http://EC2_PUBLIC_IP

Nginx 收到請求之後,再把 /api/... 的請求轉給 Node.js。


二、建立 AWS EC2

首先在 AWS 建立 EC2。

我選擇:

OS:Ubuntu
架構:64-bit

建立完成後會取得:

Public IPv4 Address

例如:

http://xxx.xxx.xxx.xxx

這個就是之後從 Windows 瀏覽器連進去的地址。


三、Windows 登入 Ubuntu

Windows 可以直接使用 SSH。

例如:

ssh -i "你的金鑰.pem" ubuntu@你的EC2_IP

成功後會看到類似:

ubuntu@ip-172-31-29-108:~$

這代表已經進入 AWS EC2。


四、第一次遇到的 Linux 權限問題

一開始執行:

apt update

結果出現:

Could not open lock file
Permission denied

原因很簡單。

Ubuntu 一般使用者不能直接修改系統套件。

所以改成:

sudo apt update

以及:

sudo apt upgrade -y

這是一個很常見的 Linux 初學者問題。


五、安裝 Docker

接下來安裝 Docker。

安裝完成後確認:

docker --version

以及:

docker compose version

如果兩個都有版本號,就可以開始建立網站。


六、建立網站目錄

我把整個專案放在:

~/mywebsite

結構如下:

mywebsite/
│
├── compose.yaml
│
├── nginx.conf
│
├── html/
│   └── index.html
│
└── server/
    ├── Dockerfile
    ├── package.json
    └── server.js

這樣前端和後端可以分開管理。


七、建立 Node.js API

Node.js 負責:

取得股票資料
↓
處理 Yahoo Finance API
↓
提供自己的 API
↓
讓前端呼叫

例如:

/api/quote
/api/markets
/api/chart
/api/health

八、Dockerfile

Node.js 使用 Docker 包起來。

FROM node:22-alpine

WORKDIR /app

COPY package.json .

RUN npm install --omit=dev

COPY server.js .

EXPOSE 3000

CMD ["node", "server.js"]

這樣 Node.js 就不需要直接安裝在 Ubuntu 主機上。


九、package.json

使用 Express:

{
  "name": "market-api",
  "version": "1.0.0",
  "type": "module",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^5.1.0"
  }
}

十、第一次遇到 Docker 問題

一開始執行:

docker compose up -d --build

結果:

failed to read dockerfile:
open Dockerfile:
no such file or directory

這個錯誤其實非常直接。

Docker Compose 找不到:

server/Dockerfile

後來確認專案結構:

server/
├── Dockerfile
├── package.json
└── server.js

問題就解決了。

這也提醒了一件事情:

Docker 出錯時,不要只看最後一行,先確認檔案結構。


十一、股票 API

後端使用 Yahoo Finance Chart API 取得資料。

例如:

AAPL
NVDA
MSFT
TSLA

台股則可以使用:

2330.TW
2317.TW
2454.TW

台灣加權指數:

^TWII

美國主要指數:

^GSPC
^IXIC

十二、即時股價 API

自己建立:

/api/quote

例如:

curl "http://localhost/api/quote?symbol=AAPL"

API 回傳:

{
  "success": true,
  "symbol": "AAPL",
  "price": 309.35,
  "previousClose": 311.3,
  "change": -1.95,
  "changePercent": -0.626,
  "currency": "USD"
}

這樣前端就不用直接碰 Yahoo。

架構變成:

Browser
   ↓
Nginx
   ↓
Node.js
   ↓
Yahoo Finance

十三、最重要的 K 線 API

一開始網站可以看到股價,但是:

K 線完全沒有。

後來發現前端呼叫:

/api/chart

但是 Node.js 根本沒有這個 API。

所以瀏覽器得到:

Cannot GET /api/chart

這就是非常典型的:

前端已經寫好了,但後端沒有對應 API。

後來在 Node.js 加入:

/api/chart

讓它支援:

1d
5d
1mo
6mo
1y
5y

例如:

curl "http://localhost/api/chart?symbol=AAPL&range=1y"

成功之後會得到:

{
  "success": true,
  "symbol": "AAPL",
  "range": "1y",
  "interval": "1d",
  "data": [
    {
      "time": "...",
      "open": 300,
      "high": 305,
      "low": 298,
      "close": 303,
      "volume": 123456
    }
  ]
}

前端再把這些資料畫成 K 線。


十四、又遇到一個很有趣的 Docker 問題

有一次:

curl "http://localhost:3000/api/chart?symbol=AAPL&range=1y"

結果:

curl: (7)
Failed to connect to localhost port 3000

但是:

docker compose ps

卻顯示:

market-api   ...   3000/tcp

注意這兩個不是同一件事情。

3000/tcp

代表:

Container 裡面有 3000 Port

不代表:

EC2:3000

已經開放。


十五、直接從 Container 裡測試

於是改成:

docker compose exec market-api \
wget -qO- \
"http://127.0.0.1:3000/api/health"

結果:

{
  "status": "ok",
  "service": "market-api"
}

這就證明:

Node.js 本身是正常的。

而且:

Market API listening on 0.0.0.0:3000

也確認 Node.js 正在監聽:

0.0.0.0:3000

十六、為什麼最後不用開 AWS 3000 Port?

因為我們使用 Nginx。

外部:

Browser
   ↓
EC2 :80

Nginx:

:80

再轉:

market-api:3000

所以 AWS Security Group 只需要讓網站使用:

80

Node.js 的:

3000

不需要直接暴露給 Internet。

這樣反而比較安全。


十七、Nginx 的角色

Nginx 在這個專案裡做兩件事。

第一:

提供 HTML

第二:

Reverse Proxy

例如:

/api/chart

會被轉給:

market-api:3000

而:

/

則直接提供:

html/index.html

十八、最後做出 Dashboard

前端最後整合:

┌────────────────────────────────────────┐
│        📊 Market Dashboard             │
├────────────────────────────────────────┤
│                                        │
│ 🇹🇼 台股                                │
│                                        │
│ 台積電      2330.TW     +...%          │
│ 鴻海        2317.TW     +...%          │
│ 聯發科      2454.TW     -...%          │
│                                        │
├────────────────────────────────────────┤
│                                        │
│ 🇺🇸 美股                                │
│                                        │
│ AAPL        Apple       +...%           │
│ NVDA        NVIDIA      +...%           │
│ MSFT        Microsoft   +...%           │
│ TSLA        Tesla       -...%           │
│                                        │
├────────────────────────────────────────┤
│                                        │
│ 📈 AAPL                                 │
│                                        │
│ 1D  5D  1M  6M  1Y  5Y                  │
│                                        │
│        🕯️ K線圖                         │
│                                        │
└────────────────────────────────────────┘

十九、增加網頁直接管理股票

後來又增加:

+ 新增股票

以及:

刪除

例如直接輸入:

NVDA
NVIDIA

就可以新增。

股票清單則存在:

localStorage

因此不需要每次修改 Server。


二十、記事本

又加入一個簡單的記事本:

📝 我的記事本

可以記錄:

今天觀察台積電
AAPL 等待回檔
NVDA 注意成交量

資料存在瀏覽器的:

localStorage

二十一、計算機

Dashboard 裡面也加入:

🧮 計算機

支援:

+
-
×
÷
%
()

所以看股票的時候可以直接計算:

100 × 1.08

或:

300000 × 0.05

二十二、目前完成的系統

到目前為止,這個小專案已經變成:

AWS EC2
│
└── Ubuntu
    │
    └── Docker
        │
        ├── Nginx
        │   │
        │   └── HTML Dashboard
        │
        └── Node.js
            │
            ├── /api/health
            ├── /api/quote
            ├── /api/markets
            └── /api/chart
                    │
                    └── Yahoo Finance

這已經不是單純的 HTML 網頁,而是一個真正的:

前端 + API Server + Reverse Proxy + Docker + Cloud Server

的小型 Web Application。


二十三、後來又準備加入即時新聞

下一步準備加入:

📰 即時新聞

架構會變成:

Browser
   ↓
Nginx
   ↓
Node.js
   ├── Yahoo Finance
   │
   └── News API

新聞 API Key 不直接放在 HTML,而是放在 Docker 的:

.env

例如:

GNEWS_API_KEY=xxxxxxxx

這樣比較不容易把 API Key 直接暴露在前端。


二十四、這次最大的收穫

這次最大的收穫其實不是做出一個股票網站。

而是第一次完整走過:

Cloud
↓
Linux
↓
Docker
↓
Nginx
↓
Node.js
↓
API
↓
Frontend
↓
External API

每一層都有可能出問題。

例如:

Linux 權限

Permission denied

解決:

sudo apt update

Docker 找不到 Dockerfile

open Dockerfile:
no such file or directory

解決:

確認專案目錄結構

Node API 不存在

Cannot GET /api/chart

解決:

增加 /api/chart

Container Port 問題

localhost:3000
Connection refused

解決:

docker compose exec

直接從 Container 裡確認 Node.js。


最後確認 API

docker compose exec market-api \
wget -qO- \
"http://127.0.0.1:3000/api/health"

看到:

{
  "status": "ok",
  "service": "market-api"
}

那一刻就代表:

我的 Node.js API 真的跑起來了。


二十五、下一步可以做到什麼?

目前這個架構還可以繼續往下發展。

例如:

☑ 台股
☑ 美股
☑ 即時報價
☑ K線
☑ Docker
☑ Nginx
☑ AWS EC2
☑ 股票新增/刪除
☑ 記事本
☑ 計算機

⬜ 即時新聞
⬜ HTTPS
⬜ 自訂網域
⬜ 使用者登入
⬜ 個人自選股
⬜ PostgreSQL / MySQL
⬜ Redis Cache
⬜ 股票價格警報
⬜ Telegram / LINE 通知
⬜ 財報資訊
⬜ 技術指標

到這裡,就可以開始把它從「自己玩的股票 Dashboard」,慢慢變成一個真正的個人投資資訊平台。


結語

這次最大的感覺是:

自己架 Server 沒有想像中難。

真正困難的是第一次遇到錯誤時,不知道問題到底在:

AWS?
Linux?
Docker?
Nginx?
Node.js?
API?
前端?

但只要一層一層拆開測試,其實就能慢慢找到問題。

例如:

docker compose ps

看 Container。

docker compose logs

看 Node.js。

curl

測 API。

docker compose exec

直接進 Container 測試。

這幾個指令,對之後維護 Docker Server 會非常常用。

最後從一台空白的 AWS Ubuntu:

AWS EC2
   ↓
Ubuntu
   ↓
Docker
   ↓
Nginx
   ↓
Node.js
   ↓
Yahoo Finance
   ↓
股票 Dashboard

一路做到可以直接用瀏覽器看台美股與 K 線。

這就是自己從零架一個 Web Application 最有趣的地方。 🚀

沒有留言:

張貼留言