我一直在阅读docs编写Dockerfiles的最佳实践。我遇到了小错误(IMHO),在进一步阅读后,其含义很清楚:
在RUN语句中单独使用apt-get更新会导致缓存问题和后续apt-get安装指令失败。
我想知道为什么失败。后来解释了他们所说的“失败”是什么意思:
由于apt get更新未运行,您的构建可能会获得过时版本的curl和nginx包。
但是,对于以下内容,我仍然无法理解他们所说的“如果没有,缓存将无效”是什么意思:
从已经在缓存中的父映像开始,将下一条指令与从该基本映像派生的所有子映像进行比较,以查看其中一个是否使用完全相同的指令构建。如果没有,则缓存无效。
这一部分在一些答案中提到,例如Docker如何知道在构建过程中何时使用缓存,何时不使用缓存?总的来说,缓存失效的概念对我来说很清楚,我已经阅读了以下内容:
Docker映像缓存何时失效?Docker使用哪种算法使缓存无效?
但“如果不是”的含义是什么?起初,我确信这个短语的意思是如果找不到这样的图像。这将是过分的——使缓存失效,这可能在以后的其他构建中有用。事实上,当我尝试以下内容时,如果没有找到图像,则不会失效:
$ docker build -t alpine:test1 - <<HITTT
> FROM apline
> RUN echo "test1"
> RUN echo "test1-2"
> HITTT
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM apline
pull access denied for apline, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
(base) nb0408:docker a.martianov$ docker build -t alpine:test1 - <<HITTT
> FROM alpine
> RUN echo "test1"
> RUN echo "test1-2"
> HITTT
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM alpine
---> 965ea09ff2eb
Step 2/3 : RUN echo "test1"
---> Running in 928453d33c7c
test1
Removing intermediate container 928453d33c7c
---> 0e93df31058d
Step 3/3 : RUN echo "test1-2"
---> Running in b068bbaf8a75
test1-2
Removing intermediate container b068bbaf8a75
---> daeaef910f21
Successfully built daeaef910f21
Successfully tagged alpine:test1
$ docker build -t alpine:test1-1 - <<HITTT
> FROM alpine
> RUN echo "test1"
> RUN echo "test1-3"
> HITTT
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM alpine
---> 965ea09ff2eb
Step 2/3 : RUN echo "test1"
---> Using cache
---> 0e93df31058d
Step 3/3 : RUN echo "test1-3"
---> Running in 74aa60a78ae1
test1-3
Removing intermediate container 74aa60a78ae1
---> 266bcc6933a8
Successfully built 266bcc6933a8
Successfully tagged alpine:test1-1
$ docker build -t alpine:test1-2 - <<HITTT
> FROM alpine
> RUN "test2"
> RUN
(base) nb0408:docker a.martianov$ docker build -t alpine:test2 - <<HITTT
> FROM alpine
> RUN echo "test2"
> RUN echo "test1-3"
> HITTT
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM alpine
---> 965ea09ff2eb
Step 2/3 : RUN echo "test2"
---> Running in 1a058ddf901c
test2
Removing intermediate container 1a058ddf901c
---> cdc31ac27a45
Step 3/3 : RUN echo "test1-3"
---> Running in 96ddd5b0f3bf
test1-3
Removing intermediate container 96ddd5b0f3bf
---> 7d8b901f3939
Successfully built 7d8b901f3939
Successfully tagged alpine:test2
$ docker build -t alpine:test1-3 - <<HITTT
> FROM alpine
> RUN echo "test1"
> RUN echo "test1-3"
> HITTT
Sending build context to Docker daemon 3.072kB
Step 1/3 : FROM alpine
---> 965ea09ff2eb
Step 2/3 : RUN echo "test1"
---> Using cache
---> 0e93df31058d
Step 3/3 : RUN echo "test1-3"
---> Using cache
---> 266bcc6933a8
Successfully built 266bcc6933a8
Successfully tagged alpine:test1-3
缓存再次用于上一次生成。“如果不是”是什么意思?
这句话的措辞应该是:
如果没有,则存在缓存未命中,并且缓存不用于此生成步骤以及Dockerfile此阶段的任何后续生成步骤。
这有点冗长,因为多级Dockerfile可能无法在一个阶段找到缓存匹配,然后在另一个阶段找到匹配。不同的构建都可以使用缓存。缓存对于特定的构建过程是“无效的”,缓存本身不会从docker主机中删除,它仍然可以用于未来的构建。
让我们关注您的原始问题(关于apt get update
),让事情变得更简单。以下示例并非基于任何最佳实践。它只是说明了你试图理解的一点。
假设您有以下Dockerfile:
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y nginx
您可以使用docker build-t myImage: date构建第一个映像。
发生的情况是:
如果ubuntu图像不存在,则将其拉取
- 一个层被创建并缓存以运行
apt-get更新
- 创建一个层缓存运行
apt安装-y nginx
现在假设您将Docker文件修改为
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y nginx openssl
然后使用与之前相同的命令再次运行构建。发生的情况是:
本地已经有一个ubuntu映像,因此它不会被拉取(除非你的原力使用--pull
)
这是否有助于您掌握缓存层的概念?
在这个特定的例子中,最好的处理方法是在一个单层中做所有的事情,确保你自己清理后:
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y nginx openssl \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
问题内容: 直到几天前,它仍能正常工作,而当我今天再次尝试构建它时,终端中出现以下错误。我尝试使用多个docker基本映像,但仍给出相同的错误。谁能帮我这个?我不认为我错过了任何东西。如果我错过了,应该早点给我错误,但是现在为什么呢? 而我的docker版本是 这是我的 问题答案: 我刚刚更改了VM Player网络设置。从更改为。现在工作了
我们正在使用@Cacheable和@CacheEvict来实现缓存。 问题是,构建缓存需要3分钟以上。根据应用程序逻辑,首先清除缓存,然后创建缓存。在此期间,如果有任何用户访问我们的应用程序,应用程序将无法发送数据,因为缓存仍在构建中。 是否有任何spring方法可以首先构建缓存,然后用新缓存替换旧缓存(除了@CachePut之外)。 谢谢,斯里坎特。
问题内容: 我目前正在为我的应用程序开发Node后端。在对其进行Docker化(docker build。)时,最长的阶段是。该指令在每个小的服务器代码更改上运行,通过使开发人员每次都等待构建完成来影响生产率。 我发现在应用程序代码所在的位置运行npm install并使用ADD指令将node_modules添加到容器中可以解决此问题,但这远非最佳实践。这有点破坏了将其Docker化的整个想法,并
问题内容: 我在搜索我的网站上具有自动完成/提前输入功能。我看到他们有时是一个例外。我们正在使用代理服务器。 引起原因:java.net.ConnectException:连接被拒绝 这是我的编码方式 谁能告诉我为什么我只在某个时候得到这个例外?是否可能是由于从Android应用程序发出搜索请求而导致此异常,因为我们的网站不支持从android应用程序发出请求 问题答案: 当您尝试打开与IP地址/
问题内容: 我将Java库打包为JAR,当我尝试从中调用方法时会抛出很多s。这些错误似乎随机出现。哪些类型的问题可能导致此错误? 问题答案: 这意味着你对库进行了一些不兼容的二进制更改,而无需重新编译客户端代码。 Java语言规范§13详细介绍了所有这些更改,最显着的是将非非私有字段/方法更改为,反之亦然。 根据新库重新编译客户端代码,你应该一切顺利。 更新:如果发布公共库,则应尽可能避免进行不兼
本文向大家介绍什么是LRU缓存?相关面试题,主要包含被问及什么是LRU缓存?时的应答技巧和注意事项,需要的朋友参考一下 参考回答: LRU(最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高 实现:使用一个链表保存缓存数据,将新数据插入到头部,每当缓存命中时,则将命中的数据移动到链表头部,当链表满的时候,将链表尾部的数据丢弃。