为什么docker从docker文件构build镜像会在不正确的构build出口时创build容器?

我使用docker从docker文件构build图像。 在这个过程中有一些错误发生,所以编译出口错误代码。

当我运行docker images我可以看到一个未标记的图像。 所以我试图删除它docker rmi xxxxx 。 但它总是失败,它说图像不能被删除,因为它被一个停止的容器使用。

所以我深入一点。 我运行docker ps -a ,现在我可以看到构build过程失败时创build的已停止容器的长列表。

为什么会有容器创build? 我认为图像在编程中就像“类”的概念,而容器是类的实例。 在图像成功构build之前,为什么会创build实例? 如何在没有所有停止的容器的情况下构build图像?

Dockerfile的每一行都会创build一个中间容器来执行该行的Dockerfile指令。

如果指令成功,将创build一个中间映像,这将成为下一个启动容器的基础(执行Dockerfile的下一行)

如果所述指令失败,则可以使容器处于退出状态,这反过来将阻塞从中创build的中间图像。
只需清理所有的容器,然后所有的图像 ,然后再试一次。

如果您试图重复构buildDockerfile,则最终会收集中间图像和容器的集合。

这就是为什么当我的构build(最终)成功时,我总是在构build脚本中清理额外的容器,图像和(使用docker 1.10+)的卷:

 cmdb="docker build${proxy}${f} -t $1 $2" # echo "cmdb='${cmdb}" if eval ${cmdb}; then docker rm $(docker ps -qa --no-trunc --filter "status=exited" 2>/dev/null) 2>/dev/null docker rmi $(docker images --filter "dangling=true" -q --no-trunc 2>/dev/null) 2>/dev/null docker volume rm $(docker volume ls -qf dangling=true 2>/dev/null) 2>/dev/null exit 0 fi 

构build过程为dockerfile中的每个步骤创build一个中间体。 就像你在这个例子中看到的那样:

 ... Removing intermediate container e07079f73a9f Step 3 : RUN cd /opt/ ---> Running in 78d480a57cca ---> 324e9006d642 Removing intermediate container 78d480a57cca Step 4 : RUN unzip /opt/mule-ee-distribution-standalone-3.7.3.zip -d /opt/ ---> Running in 81aa445c770c ... ---> e702e1cff4ee ---> removing intermediate container 81aa445c770c 

为了加快构build过程,中间容器将被用作caching。 这些容器将在成功构build后被删除,但是当您尝试多次构build“旧”中间容器和图像时,它们仍然会在您的系统上。

如果您希望在构build完成后保留中间容器,则必须使用--rm=false 。 默认情况下它是true所以在成功构build之后,中间容器将被删除。 在使用中间容器期间构build失败时,该容器将退出。 这个容器的中间'图像'的标签是<none>:<none> ,不能正常删除,因为这个图像有一个(兴奋的)容器。 您可以通过使用-f(强制)标志删除图像: docker rmi -f image-id