摘要: 拿掉 360-player-web(nginx)服務與 docker/nginx/,改在 server.js 用 node:https 直接提供 HTTPS,部署從兩個容器變成一個。 根本原因: 先前為了 TLS 而多開一個 nginx 容器。分開的主因是「憑證續期時能 reload 而不重啟 app」——重啟會殺掉正在跑的 ffmpeg 轉檔,一部 4K 360 影片動輒數小時。 但 Node 的 https.Server 本來就有 setSecureContext(),可以熱換憑證不重啟行程, 這個理由不成立,多一個容器只是多一層維護成本。 影響: - 需維護額外的 nginx 映像檔與 entrypoint.sh - 影片經反向代理多一跳,且必須小心處理 proxy_buffering 與 SSE 逾時, 設錯會讓 Range 串流被寫進暫存檔、或讓轉檔進度停止更新 修法: - server.js 新增 TLS:讀取 SSL_CERT_DIR 的憑證,以 fs.watch 監看該資料夾, 檔案變動時 debounce 1 秒後呼叫 setSecureContext() 熱套用 - 中介憑證串進 cert 而非 ca:Node 只送出 cert 的內容,ca 是驗證對方用的 信任庫、不會送給瀏覽器,放錯會導致憑證鏈不完整 - 串接前正規化 PEM(去 CRLF、補結尾換行),沿用原 nginx entrypoint 的處理 - config.json 新增 httpsPort(預設 0 = 停用)與 certDir,本機開發不需憑證; 憑證讀不到時退回只提供 HTTP 並印警告,不讓服務起不來 - docker-compose.yml 併回單一服務,憑證改掛 /certs;Dockerfile 補上 HTTPS_PORT、SSL_CERT_DIR,EXPOSE 改為 8443 - 刪除 docker/nginx/ 驗證(實機執行,非僅靜態檢查): - 以 SSL_CERT_DIR=/volume1/docker/certs 啟動,log 顯示 「HTTPS:jianmiau.tk — 14 天後到期」,https 的 /api/config 回 200 - openssl s_client 確認送出完整三層憑證鏈 (jianmiau.tk → Let's Encrypt YR2 → ISRG Root YR) - HTTPS 上的 Range 請求正常:檔頭與中段各取一段皆回 206 且長度正確 - 熱換測試:換上 CN=hotswap-test.local 的自簽憑證後,log 出現 「憑證已重新載入」,s_client 讀到新 CN,且行程 PID 與啟動時間不變 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
34 lines
985 B
Docker
34 lines
985 B
Docker
FROM node:22-alpine
|
||
|
||
# ffmpeg / ffprobe:偵測 360 metadata 與轉檔。
|
||
# intel-media-driver / libva-intel-driver:NAS 有 Intel 內顯並把 /dev/dri 掛進來時,可用 VAAPI 硬體轉檔。
|
||
# tini:正確回收 ffmpeg 子程序、把 docker stop 的 SIGTERM 轉給 node。
|
||
RUN apk add --no-cache ffmpeg intel-media-driver libva-intel-driver tini
|
||
|
||
WORKDIR /app
|
||
|
||
ENV NODE_ENV=production \
|
||
PORT=8360 \
|
||
HTTPS_PORT=8443 \
|
||
HOST=0.0.0.0 \
|
||
VIDEO_DIR=/videos \
|
||
CACHE_DIR=/cache \
|
||
SSL_CERT_DIR=/certs
|
||
|
||
COPY package*.json ./
|
||
RUN npm ci --omit=dev && npm cache clean --force
|
||
|
||
COPY server.js config.json ./
|
||
COPY lib ./lib
|
||
COPY public ./public
|
||
|
||
VOLUME ["/videos", "/cache"]
|
||
EXPOSE 8443
|
||
|
||
# HEALTHCHECK 走容器內的 HTTP,不受憑證影響(8360 不對外開)。
|
||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||
CMD wget -qO- http://127.0.0.1:8360/api/config >/dev/null || exit 1
|
||
|
||
ENTRYPOINT ["tini", "--"]
|
||
CMD ["node", "server.js"]
|