如何强制Docker进行映像的干净构建


811

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

$ docker build -t u12_core -f u12_core .

当我尝试使用同一命令重建它时,它正在使用构建缓存,例如:

Step 1 : FROM ubuntu:12.04
 ---> eb965dfb09d2
Step 2 : MAINTAINER Pavan Gupta <pavan.gupta@gmail.com>
 ---> Using cache
 ---> 4354ccf9dcd8
Step 3 : RUN apt-get update
 ---> Using cache
 ---> bcbca2fcf204
Step 4 : RUN apt-get install -y openjdk-7-jdk
 ---> Using cache
 ---> 103f1a261d44
Step 5 : RUN apt-get install -y openssh-server
 ---> Using cache
 ---> dde41f8d0904
Step 6 : RUN apt-get install -y git-core
 ---> Using cache
 ---> 9be002f08b6a
Step 7 : RUN apt-get install -y build-essential
 ---> Using cache
 ---> a752fd73a698
Step 8 : RUN apt-get install -y logrotate
 ---> Using cache
 ---> 93bca09b509d
Step 9 : RUN apt-get install -y lsb-release
 ---> Using cache
 ---> fd4d10cf18bc
Step 10 : RUN mkdir /var/run/sshd
 ---> Using cache
 ---> 63b4ecc39ff0
Step 11 : RUN echo 'root:root' | chpasswd
 ---> Using cache
 ---> 9532e31518a6
Step 12 : RUN sed -i 's/PermitRootLogin without-password/PermitRootLogin yes/' /etc/ssh/sshd_config
 ---> Using cache
 ---> 47d1660bd544
Step 13 : RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
 ---> Using cache
 ---> d1f97f1c52f7
Step 14 : RUN wget -O aerospike.tgz 'http://aerospike.com/download/server/latest/artifact/ubuntu12'
 ---> Using cache
 ---> bd7dde7a98b9
Step 15 : RUN tar -xvf aerospike.tgz
 ---> Using cache
 ---> 54adaa09921f
Step 16 : RUN dpkg -i aerospike-server-community-*/*.deb
 ---> Using cache
 ---> 11aba013eea5
Step 17 : EXPOSE 22 3000 3001 3002 3003
 ---> Using cache
 ---> e33aaa78a931
Step 18 : CMD /usr/sbin/sshd -D
 ---> Using cache
 ---> 25f5fe70fa84
Successfully built 25f5fe70fa84

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


10
顺便说一句,您通常应尽量减少RUN指令的数量。
三胞胎

4
@tripleee你能解释为什么吗?
雅。

9
@Ya。过去,Docker总是为每个RUN指令创建一个单独的层,因此Dockerfile具有多个RUN指令的会消耗大量的磁盘空间。但是在最近的版本中,这显然已经有所改进。
Tripleee '19

当我尝试时docker-compose up -d,可以在哪里使用--no-cache

@Oo这是不可能的。您首先要做的是docker-compose build --no-cache,然后docker-compose up -d
马丁·梅尔卡

Answers:


1436

有一个--no-cache选项:

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

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


86
另请注意,该功能--no-cache适用于docker-compose build
Blackus

41
您可能还想使用--pull。这将告诉docker获取基础映像的最新版本。除了--no-cache您已经拥有基础映像(例如:)ubuntu/latest并且自上次拉动基础映像以来已对其进行更新之外,这是必要的。在此处查看文档。
Collin Krawll '18

2
@CollinKrawll:这个--pull选项对我有用。只是--no-cache,构建仍然崩溃。放好--pull,构建成功!谢谢!
鄂尔多斯-培根

1
如果有人在打电话给docker build,那不是假设他们想在没有缓存的情况下进行重建吗?在哪种用例中,有人要构建图像并使用以前构建的图像?<rant>我只是迷失了一天,因为较早的构建默默地失败了,但已成功完成了“成功”,并且我正在使用损坏的图像,无法理解为什么对构建脚本的更新无法正常工作</ rant>
Jeff

3
@Jeff开发docker映像时,docker build将仅重做已修改的图层/步骤。如果我有五个步骤,并在索引3处添加了新步骤,则可以重复使用与步骤1和2相关的图层。这大大加快了开发进程
薄片

129

在某些极端情况下,避免重复发生构建失败的唯一方法是运行:

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 them
Are you sure you want to continue? [y/N]

这当然不是问题的直接答案,但可以挽救一些生命……确实挽救了我的生命。


8
添加-a -f会使它更好
-Ravi

1
@IulianOnofrei为我工作,Docker version 17.09.0-ce, build afdb6d4
Per Lundberg

1
@PerLundberg,我更新docker到了相同的版本,它可以工作,谢谢。
Iulian Onofrei

1
对于这种情况,这是一种过大的手段,如果您不想删除所有内容,则不是一个有用的答案。
M_dk

1
这甚至会删除已停止容器的图像,这可能是您不想要的。Docker的最新版本具有docker builder prune清除缓存的构建层的命令。从堆栈溢出中盲目复制命令后,就掉入陷阱了。
Evil Azrael

58

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

我们的Dockerfile是:

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

但应该是:

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

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

请参阅:编写Dockerfile的最佳实践


10
“本来应该是”具有误导性。如果Docker看到它具有缓存的副本,RUN apt-get update && apt-get -y install php5-fpm您仍然会看到它与旧内容一起被重用。
三胞胎

10
其实这仍然是有意义的加入他们的行列,因为否则,如果您更改安装线,它仍然会使用旧的包缓存,这往往会产生问题,如果缓存过期了(通常,文件会404)
约翰·查德威克

18

为确保完全重建您的构建,包括检查基础映像是否有更新,请在构建时使用以下选项:

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

--pull -这将触发对使用FROM引用的基本映像的拉动,以确保获得最新版本。

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

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

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

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

13

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

您从步骤3到步骤9运行了几次安装(顺便说一句,我宁愿使用一个衬垫),如果您不希望每次构建映像时都需要重新运行这些步骤,则可以Dockerfile在进行wget说明之前,请先通过临时步骤修改您的内容。

我曾经做过类似的事情RUN ls .,并将其更改为RUN ls ./then RUN ls ./.,依此类推,对wget

当然,您可以执行一些操作,例如RUN echo 'test1' > test && rm test增加'test1每次迭代的数量。

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


3
要能在一定点后,以不使用高速缓存的能力是许多要求(见功能github.com/moby/moby/issues/1996用于缓存的替代品清除)
leszek.hanusz

13

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


5

这里的大多数信息都是正确的。
这里是它们的汇编以及我的使用方式。

这个想法是坚持推荐的方法(构建特定的,对其他存储的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 builder和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

说的是 :

警告!这将删除:
  -所有停止的容器
  -至少一个容器未使用的所有网络
  -所有没有至少一个关联容器的图像
  -所有构建缓存

使用该超级删除命令可能还不够,因为它很大程度上取决于容器的状态(运行与否)。当该命令不够用时,我会尝试仔细考虑哪些Docker容器可能会对我们的docker构建产生副作用,并允许退出这些容器以允许使用命令将其删除。


3

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

要不提示就清除所有缓存: docker builder prune -af

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.