Yu-Jack / yu-jack.github.io

This is a blog.
https://yu-jack.github.io/
9 stars 0 forks source link

node in docker best practice #7

Open Yu-Jack opened 2 years ago

Yu-Jack commented 2 years ago

一些文章還停留在一些比較舊版描述,另外描述也不太清楚,重新自己寫一篇紀錄

Yu-Jack commented 2 years ago

先簡單紀錄

文章中有提到 npm run command 不會 forward signal 的問題,經過測試在 v4 的時候用 npm start 的方式去運行是不會 forward signal,而在 v6 之後是沒有問題的,所以文章沒有說太仔細,所以不論是用 node src/index.js or npm start or /bin/sh -c node src/index.js 其實都可以正常 forward signal 過去

(以下收到訊號是以 docker kill --signal=SIGINT 去送的)

而 tini 真正用途是,如果 container 是用 node index.js 啟動伺服器的話,當她收到 SIGINT / SIGTERM 訊號是不會有任何反應,也就代表不會關閉 server,最後透過 docker stop 關閉的話,會變成 137 強制關閉,而透過 tini 啟動的話,收到 SIGINT / SIGTERM 訊號會正常關閉 node server (130 + 143)。

那因為 v12 npm 指令結構不一樣了,所以直接用 npm start 去啟動時,接收到 SIGINT / SIGTERM 的行為會跟 tini 一樣幫忙關閉,差別在於 npm 關閉都會是以 exit code 0 跳出,這問題出在看不出來是怎樣被關閉的,130 代表示 CTRL+C,143 代表示 kill -15 正常終止,另外如果是 docker stop 的話,npm 會以 kill -9 強制終止,tini 會以 kill -15 跳出,而盡量最好是以 kill -15 跳出會比較適合,因為 kill -9 是不會給程式有準備時間去關閉,可能會導致資料丟失等等問題,是一個不會被阻塞的訊號,但 kill -15 則是會被阻塞,也就代表會讓程式有能力去做 graceful shutdown。

但如果 node 程式有針對 SIGINT / SIGTERM listen 的話,tini 則不會把 server 給關閉,就變成需要由 node 自行去做關閉。所以預期 node 正常被關閉應該是要拿到 128 + 15 (TERM) 的訊號去做 graceful shutdown 後得到 exit code 0,而不是最後被 128 + 9 (KILL) 的訊號強制關閉。

[1] https://maximorlov.com/process-signals-inside-docker-containers/ [2] https://developpaper.com/avoid-running-nodejs-as-pid-1-under-the-docker-image/ [3] https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#handling-kernel-signals