ChatGPT解决这个技术问题 Extra ChatGPT

如何强制 Docker 干净构建映像

我已经使用以下命令从 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 在没有缓存的情况下重建干净的映像?

顺便说一句,您通常应该尽量减少 RUN 指令的数量。
@tripleee 你能解释一下为什么吗?
@雅。过去,Docker 总是为每个 RUN 指令创建一个单独的层,因此具有许多 RUN 指令的 Dockerfile 会消耗大量磁盘空间;但这显然在最近的版本中有所改进。
当我尝试 docker-compose up -d 时,我可以在哪里使用 --no-cache
@Oo 那是不可能的。您首先必须执行 docker-compose build --no-cache,然后执行 docker-compose up -d

P
Peter Mortensen

有一个 --no-cache 选项:

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

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


另请注意,--no-cachedocker-compose build 一起使用。
您可能还想使用 --pull。这将告诉 docker 获取最新版本的基础镜像。如果您已经拥有基本映像(例如:ubuntu/latest)并且自上次拉取后基本映像已更新,则除了 --no-cache 之外,这是必需的。请参阅文档 here
@CollinKrawll:--pull 选项对我有用。只是 --no-cache,构建仍然失败。也加入 --pull,构建成功!谢谢!
@Jeff 当您开发 docker 映像时, docker build 只会重做已修改的层/步骤。如果我有五个步骤,并且我在索引 3 处添加了一个新步骤,那么与步骤 1 和 2 关联的层可以被重新使用。这大大加快了开发过程
@Jeff 我必须构建需要 2 小时才能完全构建的图像。在这些情况下,缓存非常有用。如果使用得当,它将节省大量时间。构建 docker 镜像以充分利用这一点是很常见的。
I
Iulian Onofrei

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

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]

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


添加 -a -f 使它更好
@IulianOnofrei 为我工作,Docker version 17.09.0-ce, build afdb6d4
如果您不想删除所有内容,这对于这种情况来说太过分了,而且不是一个可用的答案。
这甚至会删除已停止容器的图像,这可能是您不想要的。最新版本的 docker 有命令 docker builder prune 来清除缓存的构建层。刚从堆栈溢出中盲目复制命令就掉入了陷阱。
这甚至不能解决问题。
M
M_dk

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

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

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

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

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

docker-compose 可以使用相同的选项:

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

请注意,如果您的 docker-compose 文件引用了一个图像,那么 --pull 选项实际上不会拉取该图像(如果已经有一个)。

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

docker-compose pull

P
Peter Mortensen

命令 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

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

请参阅:Best practices for writing Dockerfiles


“应该”具有误导性。如果 Docker 发现它具有 RUN apt-get update && apt-get -y install php5-fpm 的缓存副本,您仍然会看到它被旧内容重用。
其实加入它们还是有意义的,因为否则如果你更改安装行,它仍然会使用旧的包缓存,如果缓存过期通常会出现问题(通常,文件会404。)
但应该是:RUN apt-get update && apt-get -y install php5-fpm && rm -rf /var/lib/apt/lists/* 事实上,在 RUN“关闭”之前清理 apt/lists 文件是最佳实践
d
davidxxx

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

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

说的是 :

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 构建造成副作用,并允许这些容器退出,以便使用该命令将它们删除。


docker image prune(不带 -a)更友好,不会破坏您可能想要的所有图像。
Y
Yash

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


P
Peter Mortensen

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

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

我曾经做过类似 RUN ls . 的操作,然后将其更改为 RUN ls ./,然后更改为 RUN ls ./.,依此类推,每次对 wget 检索到的 tarball 进行修改

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

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


能够在某个时间点后不使用缓存的能力是许多人要求的功能(请参阅 github.com/moby/moby/issues/1996 了解缓存破坏的替代方案)
0
0bel1sk

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

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


OP 没有使用 buildkit
R
Rabhi salim

在我非常独特的情况下,我的 intellij 被窃听了。更改整个 Dockerfile 并没有产生任何影响,并且它的旧版本将运行。

Closing the terminal window and reopening it fixed the issue

S
Sliq

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

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