如何强制Docker构建一个干净的镜像

我已经使用下面的命令从Docker文件构建了一个Docker映像。

$ docker build -t u12_core -f u12_core .

当我尝试使用相同的命令重建它时,它使用的构建缓存如下:

Step 1 : FROM ubuntu:12.04---> eb965dfb09d2Step 2 : MAINTAINER Pavan Gupta <pavan.gupta@gmail.com>---> Using cache---> 4354ccf9dcd8Step 3 : RUN apt-get update---> Using cache---> bcbca2fcf204Step 4 : RUN apt-get install -y openjdk-7-jdk---> Using cache---> 103f1a261d44Step 5 : RUN apt-get install -y openssh-server---> Using cache---> dde41f8d0904Step 6 : RUN apt-get install -y git-core---> Using cache---> 9be002f08b6aStep 7 : RUN apt-get install -y build-essential---> Using cache---> a752fd73a698Step 8 : RUN apt-get install -y logrotate---> Using cache---> 93bca09b509dStep 9 : RUN apt-get install -y lsb-release---> Using cache---> fd4d10cf18bcStep 10 : RUN mkdir /var/run/sshd---> Using cache---> 63b4ecc39ff0Step 11 : RUN echo 'root:root' | chpasswd---> Using cache---> 9532e31518a6Step 12 : RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config---> Using cache---> 47d1660bd544Step 13 : RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd---> Using cache---> d1f97f1c52f7Step 14 : RUN wget -O aerospike.tgz 'http://aerospike.com/download/server/latest/artifact/ubuntu12'---> Using cache---> bd7dde7a98b9Step 15 : RUN tar -xvf aerospike.tgz---> Using cache---> 54adaa09921fStep 16 : RUN dpkg -i aerospike-server-community-*/*.deb---> Using cache---> 11aba013eea5Step 17 : EXPOSE 22 3000 3001 3002 3003---> Using cache---> e33aaa78a931Step 18 : CMD /usr/sbin/sshd -D---> Using cache---> 25f5fe70fa84Successfully built 25f5fe70fa84

缓存显示已安装Aerospike。但是,我在从此映像生成的容器中找不到它,所以我想在不使用缓存的情况下重建此映像。如何强制Docker重建没有缓存的干净映像?

1100335 次浏览

有一个--no-cache选项:

docker build --no-cache -t u12_core -f u12_core .

在旧版本的Docker中,您需要传递--no-cache=true,但情况不再如此。

命令docker build --no-cache .解决了我们类似的问题。

我们的Dockerfile是:

RUN apt-get updateRUN apt-get -y install php5-fpm

但应该是:

RUN apt-get update && apt-get -y install php5-fpm

为了防止缓存更新并单独安装。

见:编写Dockerfile的最佳实践

在某些极端情况下,解决反复出现的构建失败的唯一方法是运行:

docker system prune

命令将要求您确认:

WARNING! This will remove:- all stopped containers- all volumes not used by at least one container- all networks not used by at least one container- all images without at least one container associated to themAre you sure you want to continue? [y/N]

这当然不是对这个问题的直接回答,但可能会挽救一些生命……它确实拯救了我的生命。

我不建议在你的情况下使用--no-cache

您正在运行从第3步到第9步的几个安装(顺便说一句,我更喜欢使用一个班轮),如果您不希望每次构建映像时重新运行这些步骤的开销,您可以在wget指令之前使用临时步骤修改您的Dockerfile

对于wget检索到的tarball所做的每次修改,我都会做类似于RUN ls .的操作,然后将其更改为RUN ls ./,然后再更改为RUN ls ./.,依此类推

当然,您可以执行类似于RUN echo 'test1' > test && rm test的操作,为每次迭代增加'test1中的数字。

它看起来很脏,但据我所知,这是继续受益于Docker缓存系统的最有效方式,当你有很多层时,它可以节省时间。

您可以使用docker builder管理构建器缓存

在没有提示的情况下清理所有缓存:docker builder prune -af

使用docker-compostrydocker-compose up -d --build --force-recreate

要确保完全重建构建,包括检查基本映像以获取更新,请在构建时使用以下选项:

--no-cache-这将强制重建已经可用的层

--pull-这将触发使用from引用的基本图像的拉取,确保您获得最新版本。

因此,完整的命令将如下所示:

docker build --pull --no-cache --tag myimage:version .

相同的选项可用于docker-compose:

docker-compose build --no-cache --pull

说明如果您的docker-compose文件引用了一个图像,如果已经有一个图像,--ull选项实际上不会拉取图像。

要强制docker-compose重新拉取它,您可以运行:

docker-compose pull

这里的大部分信息都是正确的。
这里是他们的汇编和我使用它们的方式。

我们的想法是坚持推荐的方法(构建特定并且对其他存储的docker对象没有影响),并在不够时尝试更激进的方法(不构建特定并且对其他存储的docker对象有影响)。

建议的做法:

1)强制执行Dockerfile中的每一步/指令:

docker build --no-cache

或者docker-compose build

docker-compose build --no-cache

我们还可以将其组合到重新创建所有容器的up子命令中:

docker-compose build --no-cache &&docker-compose up -d --force-recreate

这些方式不使用缓存,而是用于docker构建器和FROM指令引用的基本映像。

2)擦除docker Builder缓存(如果我们使用Buildkit,我们很可能需要它):

docker builder prune -af

3)如果我们不想使用父图像的缓存,我们可能会尝试删除它们,例如:

docker image rm -f fooParentImage

在大多数情况下,这三件事完全足以让我们的形象干净地建立。
所以我们应该努力坚持下去。

更激进的方法:

在构建过程中似乎Docker缓存中的某些对象仍在使用并且看起来可重复的角落情况下,我们应该尝试了解能够非常具体地擦除缺失部分的原因。如果我们真的找不到从头开始重建的方法,还有其他方法,但重要的是要记住,这些通常会删除比需要的多得多的东西。所以当我们不在本地/开发环境中时,我们应该谨慎地使用它们。

1)删除所有没有至少一个容器关联的图像:

docker image prune -a

2)删除更多内容:

docker system prune -a

它说:

WARNING! This will remove:- all stopped containers- all networks not used by at least one container- all images without at least one container associated to them- all build cache

使用超级删除命令可能还不够,因为它强烈依赖于容器的状态(运行与否)。当该命令还不够时,我会仔细考虑哪些docker容器可能会对我们的docker构建造成副作用,并允许退出这些容器,以便使用命令删除它们。

GUI驱动的方法:打开docker桌面工具(通常随Docker附带):

  1. 在“容器/应用程序”下停止该映像的所有正在运行的实例
  2. 在“图片”下删除构建镜像(将鼠标悬停在框名上以获取上下文菜单),最终也是底层基础图像