为什么docker从docker文件构建映像会在构建退出错误时创建容器?

时间:2016-04-23 08:28:54

标签: docker docker-image

我正在使用docker从docker文件构建图像。在这个过程中发生了一些错误,因此构建退出时出现错误代码。

当我跑docker images时,我可以看到未标记的图像。所以我试图将其删除docker rmi xxxxx。但它总是失败,它说图像无法删除,因为它被停止的容器使用。

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

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

2 个答案:

答案 0 :(得分:5)

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

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

如果所述指令失败,则可以使容器处于“退出”状态,从而阻止其创建的中间图像。
只需cleanup all the containers then all the images,然后重试。

如果您尝试重复构建Dockerfile,最终会得到一组中间图像和容器。

这就是为什么当我的构建(最终)成功时,我总是在我的build script中清理额外的容器,图像和(使用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

答案 1 :(得分:2)

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

...
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

为了加快构建过程,中间容器将用作缓存。这些容器将在成功构建后删除,但是当您尝试多次构建时,这些容器将会被删除。中间容器和图像仍将在您的系统上。

如果您希望在构建完成后保留中间容器,则必须使用--rm=false。默认情况下它是true所以在成功构建之后,中间容器将被删除。在使用中间容器期间构建失败时,此容器将退出。这个容器的中间图像&#39;有标签<none>:<none>并且无法正常删除,因为有一个(兴奋的)容器来自此图片。您可以使用-f(强制)标记删除图像:docker rmi -f image-id