docker commit采坑記錄


最近使用docker commit碰到了一個小坑,記錄分享一下。

問題現象記錄:

使用官方docker鏡像 nginx 1.19.2,想要修改鏡像中nginx.conf中配置值,方法如下:(注:可以直接通過文件修改,此處為了給docker commit舉例用)

  1. 使用某個鏡像運行了一個容器(docker run image:tag /bin/bash)
  2. 在容器內修改了程序的啟動參數
  3. 使用這個容器生成它需要的image(docker commit containerID)

理論上這個操作是沒有任何問題的,實際上新的image一運行立刻就退出了 ,容器的狀態為Exit(0)

查看日志,發現沒有打印任何日志,推測很大的可能性是執行命令不是阻塞程序,執行完就直接退出了。

驗證一下:通過docker ps對比新舊image容器的CMD指令,老image的CMD='nginx -g daemon off;’,新image的CMD=‘/bin/bash’,確認問題了,修改后的CMD覆蓋掉了修改前的。

 

問題根源分析

1.為什么CMD會被修改

回顧全程看看cmd命令是什么時候被修改的:
  修改前image的cmd=‘nginx -g daemon off;’,然后docker run -it image:tag /bin/bash啟動了容器並且進入到容器內部進行修改,最后執行docker commit 。
很明顯docker commit將容器當前使用的cmd(/bin/bash)設置為新創建的image的CMD。也就是原來image的cmd被剛才commit時指定的容器cmd覆蓋了。
為什么會覆蓋吶?docker官方描述如下:
If you list more than one CMD then only the last CMD will take effect。如果有多條CMD命令,僅最后一條CMD命令生效。
老image的dockerfile中CMD是這樣的:
 CMD ["nginx" "-g" "daemon off;"]

執行docker run命令時,最后一條cmd由原來的 nginx -g daemon off; 變為/bin/bash

docker run -it image:tag /bin/bash     #容器主進程變為/bin/bash

執行docker commit時,當前容器的cmd保存最后一條/bin/bash

2.為什么新CMD‘/bin/bash’導致容器退出
因為Docker 不是虛擬機, 容器就是進程。既然是進程,那么在啟動容器的時候,需要指定所運行的程序及參數。 CMD 指令就是用於指定默認的容器主進程的啟動命令的
對於容器而言,其啟動程序就是容器應用進程,容器就是為了主進程而存在的,主進程退出,容器就失去了存在的意義,從而退出,其它輔助進程不是它需要關心的東西。
為了保證容器不退出,容器的主進程(即image的dockfile中CMD執行的命令)必須是常駐運行的(一直掛起的例如tail top等前台命令,后台命令一般執行后就會退出)。
docker官方描述如下:
The main purpose of a CMD is to provide defaults for an executing container。CMD主要目的是為可執行容器提供默認命令。

問題解決方案

1. docker run啟動容器時,不指定CMD (docker run -dit image:tag,無 /bin/bash)。

  啟動容器時,不指定CMD,則使用默認cmd運行容器。commit時自動保留原鏡像的默認CMD。

  若需要進入容器bash環境編輯容器,再使用docker exec -it containerID /bin/bash即可。

2. docker commit時使用--change參數替換image中的cmd.

  比如:--change=‘CMD ["nginx", "-g", "daemon off;"]' 

 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM