背景:正在學習docker期間,接到一個任務,通過docker部署一個應用A。該應用A類似於之前部署的應用B,結果很自然地犯了形而上學的錯誤。
思路:基於dockerfile+docker-compose.yml來部署。
基本操作:編寫dockerfile,制作基礎鏡像;docker-compose.yml作端口映射,數據卷掛載等操作。
出現問題:docker-compose up時,創建容器。docker ps看到容器的狀態為restart狀態,而不是正常的up。
難點:容器外部docker logs沒能查看到容器應用運行的任何日志信息。同時因容器不斷處於restart態,無法進入容器內查看應用運行的任何日志信息。
定位:
1、懷疑是docker-compose.yml中設置的內存太少,把內存大小限制設置為4G,沒能決定問題。排除內存不夠原因。
2、檢查docker-compose.yml端口映射,確保沒有與現有應用端口沖突。排除端口問題。
3、檢查docker-compose.yml中數據卷的掛載及CMD的命令執行參數。排除數據掛載及命令參數問題。
4、懷疑是應用的執行權限問題,可是在不作修改情況下,docker容器中默認用的就是root權限。排除權限問題
5、本地非docker容器內運行該應用,一切正常。排除程序自身問題。
6、容器中前后台進程的影響,A是前台,B后台。(最終元凶)
出現問題原因:dockerfile中的CMD命令,是容器啟動后運行的第一條命令,其PID為1。而Docker容器僅在它的1號進程運行時,會保持運行。如果1號進程退出了,Docker容器也就退出了。而我們要部署的應用屬於后台進程,容器運行時,pid為1的進程不是A,而是bash,這個bash執行完指令后就掛了。同時因為容器中設置的restart策略為unless-stopped,因此會看到容器一直處於restart態。作為驗證,將原本在容器中運行正常的B應用,在其CMD的執行參數中加上&,會看到B容器應用也一直處於restart態。
解決:在運行A應用后增加&&tail -f XXX.log,至此容器運行正常,進入A容器內進行相關區塊鏈測試符合預期。
結論:容器生命周期和其內部PID為1的進程一致。