這個 Nginx proxy 安裝在 TAMS 主機上,統一處理 HTTPS/WSS,並依網域將流量送往 TAMS、HMI 與 rosbridge。
| 網址 | 目的地 |
|---|---|
https://tams.hospital.internal | TAMS frontend、backend、Swagger、Socket.IO |
https://hmi-amr701.hospital.internal | HMI frontend、backend、Swagger、Socket.IO |
wss://amr701.hospital.internal | AMR rosbridge |
以下命令都從 PolyMedX workspace 根目錄執行。
前置條件
- Docker 與 Docker Compose 已啟動。
- TAMS 主機可連到 AMR 的
5173、3000、9090。 - 主機的
80、443尚未被其他程式占用;測試時也可改用8080、8443。 - TAMS backend 與 frontend 使用同一個
tams-network。
建立設定
make edge-init
這會建立 workspace-config/edge-proxy/.env;若檔案已存在則保留原檔,不會覆寫。
開發環境範例:
SSL_BASE_DOMAIN=hospital.internal
TAMS_DOMAIN=tams.hospital.internal
HMI_DOMAIN=hmi-amr701.hospital.internal
AMR_DOMAIN=amr701.hospital.internal
TAMS_APP_UPSTREAM=frontend:80
TAMS_API_UPSTREAM=backend:3000
TAMS_API_PREFIX=/api
AMR_IP=172.18.35.29
HMI_APP_UPSTREAM=${AMR_IP}:5173
HMI_API_UPSTREAM=${AMR_IP}:3000
ROS_BRIDGE_UPSTREAM=${AMR_IP}:9090
SELF_SIGNED=true
HSTS_MAX_AGE=0
HTTP_PORT=80
HTTPS_PORT=443
注意:
- 本機開發 Compose 的 backend 通常使用
backend:3000。 - 正式 Compose 的 backend 使用
backend:9000。 TAMS_API_PREFIX必須與 backend 的DEFAULT_API_ROUTER_PREFIX相同。- 容器中的
localhost是容器自己;主機上的服務要使用host.docker.internal:<port>。
設定測試網域
不需要先購買網域。假設 TAMS 主機 IP 是 192.168.1.100,在每台測試用戶端的 /etc/hosts 加入:
192.168.1.100 tams.hospital.internal
192.168.1.100 hmi-amr701.hospital.internal
192.168.1.100 amr701.hospital.internal
三個名稱可以指向同一個 IP;Nginx 會根據 hostname 決定 upstream。不要只使用 https://192.168.1.100,否則無法區分 TAMS、HMI 與 rosbridge。
只用 curl 測試時,可以不修改 /etc/hosts:
curl -k \
--resolve tams.hospital.internal:443:192.168.1.100 \
https://tams.hospital.internal/
啟動 upstream 服務
開發環境:
make build-up
make ps
正式環境:
make prod-build-up
make prod-ps
另外確認 HMI frontend、HMI backend 與 rosbridge 已在 AMR 上啟動。
檢查 Docker network:
docker network inspect tams-network
TAMS backend、frontend 與 nginx-ssl 最終都應連到 tams-network。
驗證設定
make edge-config
make edge-validate
edge-config:檢查 Compose 展開結果。edge-validate:建置 image、產生 Nginx 設定並執行nginx -t。
edge-validate 不要求 upstream 已在線;它會在語法檢查時暫時使用 loopback IP。
啟動 edge proxy
make edge-build-up
make edge-ps
make edge-logs
正常啟動後測試:
make edge-smoke
從另一台電腦測試 proxy:
EDGE_PROXY_HOST=192.168.1.100 make edge-smoke
Smoke test 會檢查:
- HTTP 是否轉址到 HTTPS。
- TAMS 與 HMI frontend。
- TAMS API 是否錯誤落入 SPA。
- Socket.IO polling handshake。
- rosbridge WSS upgrade。
信任開發憑證
SELF_SIGNED=true 產生的是開發憑證。瀏覽器出現 ERR_CERT_AUTHORITY_INVALID 是正常現象;憑證必須安裝在開啟網頁的用戶端,而不只是 TAMS 主機。
macOS 先確認憑證:
openssl x509 \
-in workspace-config/edge-proxy/certs/server.crt \
-noout -subject -issuer -dates -ext subjectAltName -fingerprint -sha256
確認是自己產生的憑證後,加入 System Keychain:
sudo security add-trusted-cert \
-d \
-r trustRoot \
-k /Library/Keychains/System.keychain \
workspace-config/edge-proxy/certs/server.crt
完全關閉並重新開啟 Chrome,再訪問:
https://tams.hospital.internal
不要在不確定來源時信任憑證。正式環境應使用醫院內部 CA 或可信任 CA 簽發的憑證。
常用命令
| 命令 | 用途 |
|---|---|
make edge-init | 安全建立 .env |
make edge-config | 展開 Compose 設定 |
make edge-validate | 建置並執行 nginx -t |
make edge-build | 只建置 image,不啟動服務 |
make edge-up | 啟動既有 image |
make edge-build-up | 建置並啟動 |
make edge-restart | 重新啟動 |
make edge-down | 停止並移除 container |
make edge-ps | 查看狀態 |
make edge-logs | 持續顯示 nginx-ssl log |
make edge-logs SERVICE=<服務名稱> | 持續顯示指定服務的 log |
make edge-smoke | 測試 proxy 與 upstream 路由 |
若正式設定放在 workspace 外:
make edge-validate EDGE_ENV=/etc/polymedx/edge-proxy.env
make edge-build-up EDGE_ENV=/etc/polymedx/edge-proxy.env
常見問題
host not found in upstream "backend"
表示 Nginx 無法透過 Docker DNS 找到 backend。依序檢查:
make ps
docker network inspect tams-network
make edge-config
make edge-restart
make edge-logs
確認 backend 已啟動並加入 tams-network。若 backend 在主機上,改用:
TAMS_API_UPSTREAM=host.docker.internal:9000
若 backend 在另一台主機,使用可達 IP:
TAMS_API_UPSTREAM=192.168.1.20:9000
502 Bad Gateway
DNS 已解析,但 upstream 沒有回應。檢查 IP、port、防火牆以及服務實際監聽位置。開發環境常見原因是把 backend:3000 誤設為 backend:9000。
ERR_CERT_AUTHORITY_INVALID
網域通常沒有問題,而是用戶端尚未信任 self-signed certificate。依「信任開發憑證」章節安裝,或改用醫院 CA 憑證。
正式環境
正式環境建議由醫院 IT 提供內部 DNS 與憑證,例如:
*.polymed.hospital.example -> <TAMS host IP>
將完整憑證鏈與 private key 放入:
workspace-config/edge-proxy/certs/server.crt
workspace-config/edge-proxy/certs/server.key
設定:
SELF_SIGNED=false
HSTS_MAX_AGE=31536000
只有在正式可信任憑證確認正常後才啟用長期 HSTS。憑證、private key 與 .env 都不可提交到 Git。
flowchart LR
subgraph Clients["用戶端"]
Browser["瀏覽器/<br/>HMI App"]
end
subgraph Edge["TAMS 主機:TLS 終止"]
Nginx["Nginx Edge Proxy<br/>憑證:*.csh.org.tw"]
end
subgraph TAMS[" TAMS Docker Network "]
TF["TAMS Frontend<br/>frontend:80"]
TB["TAMS Backend<br/>backend:9000"]
RMF["RMF API<br/>rmf-api-service:9001"]
Redis["Redis"]
end
DB["MongoDB"]
subgraph AMR["AMR 主機"]
HF["HMI Frontend<br/>AMR_IP:5173"]
HB["HMI Backend<br/>AMR_IP:3000"]
ROS["rosbridge<br/>AMR_IP:9090"]
end
Browser ==>|"HTTPS:tams.csh.org.tw"| Nginx
Browser ==>|"HTTPS:hmi-amr701.csh.org.tw"| Nginx
Browser ==>|"WSS:amr701.csh.org.tw"| Nginx
Nginx -.->|"HTTP"| TF
Nginx -.->|"HTTP"| TB
Nginx -.->|"HTTP 跨主機"| HF
Nginx -.->|"HTTP 跨主機"| HB
Nginx -.->|"WebSocket 跨主機"| ROS
TB -.->|"HTTP"| RMF
TB -.->|"Redis Protocol"| Redis
TB -.->|"MongoDB Protocol"| DB
classDef tls fill:#d8f3dc,stroke:#2d6a4f,color:#081c15
classDef plain fill:#fff3bf,stroke:#e67700,color:#5f3b00
class Nginx tls
class TF,TB,RMF,DB,Redis,HF,HB,ROS plain
flowchart LR
Browser["瀏覽器"] ==>|"HTTPS/WSS 加密"| Nginx
subgraph TAMSHost["TAMS 主機"]
Nginx["Nginx Edge Proxy<br/>*.csh.org.tw"]
subgraph Docker["TAMS Docker Network"]
Frontend["TAMS Frontend"]
Backend["TAMS Backend"]
RMF["RMF API"]
Redis["Redis"]
end
end
MongoDB["MongoDB"]
subgraph AMRHost["AMR 主機"]
HMI["HMI Frontend/Backend"]
Rosbridge["rosbridge"]
end
Nginx -.->|"HTTP"| Frontend
Nginx -.->|"HTTP"| Backend
Nginx -.->|"HTTP"| HMI
Nginx -.->|"WebSocket"| Rosbridge
Backend -.->|"HTTP"| RMF
Backend -.->|"Redis Protocol"| Redis
Backend -->|"MongoDB Protocol<br/>可選 TLS"| MongoDB
classDef secure fill:#d8f3dc,stroke:#2d6a4f
classDef plain fill:#fff3bf,stroke:#e67700
classDef optional fill:#e7f5ff,stroke:#1971c2
class Nginx secure
class Frontend,Backend,RMF,Redis,HMI,Rosbridge plain
class MongoDB optional