要如何在 container 裡運行多個 process
延續 Docker 啟動 process 的主題,因 container 即 process,因此合理的設計方法會是一個 container 只執行一個 process。而且 Dockerfile 也只能設定一個 ENTRYPOINT 和 CMD,實際上也很難跑多個 process。
但如果真的需要一個 container 同時跑多個 process 的話,該怎麼做呢?
開始前,先來定義簡單的目標:
- 使用 httpd image,Alpine 版本
- 在同一個 container 裡,同時啟動 httpd 與 top 兩個指令
使用 docker exec
山不轉,路轉。即然 Dockerfile 或 docker run
不行的話,那就先 docker run
再 docker exec
吧!
# 啟動 Apache |
這個方法非常單純易懂,但代價也是龐大的。這個做法的問題點昨天有提到,主要是 docker exec
的 process 在 PID 1 process 結束的時候,沒有辦法正常地收到 SIGTERM
通知。
再來另一個也非常麻煩的問題是,無法使用「一個」 Docker 指令完成啟動兩個 process,即使是 Docker Compose 也一樣。代表這需要靠腳本或其他方法來組合 Docker 指令,這將會讓維運 container 的人吃盡苦頭。
若 docker exec
不適合的話,那接下來也只剩一種方向:在 CMD 或 ENTRYPOINT 執行某個特別的腳本或程式,由它來啟動所有需要的 process。
使用 shell script
寫一個 shell script,讓它去啟動每個 process ,然後在結尾跑一個無窮迴圈即可:
|
這個方法有一樣的問題--process 無法收到 SIGTERM
信號,而且比 docker exec
更加嚴重。docker exec
的方法,至少還會有一個 process 收到信號,而 shell script 方法則是所有 process 都收不到信號。
可以用類似的概念實作 Chromium + PHP for Docker:
|
使用 Supervisor
Supervisor 是一個能控制多個 process 執行的管理器。以 Supervisor 改寫 Dockerfile 如下:
FROM httpd:2.4-alpine |
這裡看到還有個設定是 supervisord.conf
,內容如下:
[supervisord] |
從執行結果的 log 可以看到 Supervisor 是跑在 PID 1,而 Apache 跑在 PID 8、top 跑在 PID 9 ,兩個 process 都有正常啟動。
2020-10-12 15:24:38,955 INFO supervisord started with pid 1 |
接著故意使用 Ctrl + C 來中止程式,可以發現 Supervisor 有把 SIGTERM 信號傳送給 Apache 與 top,並把中止程式的任務完成:
2020-10-12 15:24:52,055 WARN received SIGINT indicating exit request |
今日自我回顧
從今天的範例可以發現,想要在同一個 container 跑多個 process 是很困難的。因此,最好的方法就是:
一個 container 只執行一個 process!