当前位置:  开发笔记 > 编程语言 > 正文

Docker - 如何更新图像

如何解决《Docker-如何更新图像》经验,为你挑选了1个好方法。

我读到docker使用图层,因此在创建a containerDockerfile,从基本图像开始,然后后续命令运行向容器添加图层,因此如果保存新容器的状态,则会有新图像.我想知道有几件事情.

如果我从Ubuntu图像开始,这是一个非常庞大和笨重的图像,因为它是一个完整的操作系统,然后我添加了一些工具并将其保存为我上传到集线器的新图像.如果有人下载我的图像,并且他们已经保存了Ubuntu图像images folder,这是否意味着他们可以跳过下载,Ubuntu因为他们已经有了图像?如果是这样,当我修改原始图像的某些部分时,这是如何工作的,Docker是否使用其缓存数据Ubuntu image在加载后有选择地将这些更改应用于它?

2.)如何通过修改Dockerfile来更新我构建的图像?我用这个设置了一个简单的django项目Dockerfile:

FROM python:3.5

ENV PYTHONBUFFERED 1
ENV APPLICATION_ROOT /app
ENV APP_ENVIRONMENT L

RUN mkdir -p $APPLICATION_ROOT
WORKDIR $APPLICATION_ROOT
ADD requirements.txt $APPLICATION_ROOT
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
ADD . $APPLICATION_ROOT

并用它来开始创建图像.所以每当我创建一个盒子时,它会加载所有这些environment variables,如果我完全重建盒子,它会重新安装包和所有附加物.我需要添加一个新的环境变量,所以我将它添加到Dockerfile了测试变量的底部:

ENV COMPOSE_CONVERT_WINDOWS_PATHS 1
ENV TEST_ENV_VAR TEST

当我删除容器和图像,并构建一个新的容器时,它似乎都相应,它告诉我它创建了新的第4步:ENV

COMPOSE_CONVERT_WINDOWS_PATHS 1
 ---> Running in 75551ea311b2
 ---> b25b60e29f18
Removing intermediate container 75551ea311b2

所以它就像在某些中间容器转换中丢失了一些东西.这是缓存系统的工作原理,每个新层都是一个intermediate container?因此,考虑到这一点,如何添加新图层,您是否总是必须在Dockerfile的底部添加新数据?或者在构建映像后将Dockerfile单独保留是否更好,只需修改container并构建新映像?

编辑我刚尝试安装一个图像,一个名为的软件包 bwawrik/bioinformatics,它是一个基于CentOS的容器,安装了各种工具.

它冻结了一半,所以我退出它,然后再次运行它,看看是否所有东西都已安装:

$ docker pull bwawrik/bioinformatics
Using default tag: latest
latest: Pulling from bwawrik/bioinformatics

a3ed95caeb02: Already exists
a3ed95caeb02: Already exists
7e78dbe53fdd: Already exists
ebcc98113eaa: Already exists
598d3c8fd678: Already exists
12520d1e1960: Already exists
9b4912d2bc7b: Already exists
c64f941884ae: Already exists
24371a4298bf: Already exists
993de48846f3: Already exists
2231b3c00b9e: Already exists
2d67c793630d: Already exists
d43673e70e8e: Already exists
fe4f50dda611: Already exists
33300f752b24: Already exists
b4eec31201d8: Already exists
f34092f697e8: Already exists
e49521d8fb4f: Already exists
8349c93680fe: Already exists
929d44a7a5a1: Already exists
09a30957f0fb: Already exists
4611e742e0b5: Already exists
25aacf0148db: Already exists
74da82504b6c: Already exists
3e0aac083b86: Already exists
f52c7e0ac000: Already exists
35eee92aaf2f: Already exists
5f6d8eb70885: Already exists
536920bfe266: Already exists
98638e678c51: Already exists
9123956b991d: Already exists
1c4c8a29cd65: Already exists
1804bf352a97: Already exists
aa6fe9359956: Already exists
e7e38d1250a9: Already exists
05e935c831dc: Already exists
b7dfc22c26f3: Already exists
1514d4797ffd: Already exists
Digest: sha256:0391808e21b7b5cc0eb44fc2dad0d7f5415115bdaafb4534c0b6a12efd47a88b
Status: Image is up to date for bwawrik/bioinformatics:latest

所以它绝对安装了包装,而不是一次性安装.这些碎片,不同的图像?



1> Dan Lowe..:

图像与容器

首先,让我澄清一些术语.

image:一个静态的,不可变的对象.这是你docker build使用a 运行时构建的东西Dockerfile.图像不是运行的东西.

图像由图层组成.图像可能只有一个图层,或者可能有多个图层.

容器:一个运行的东西.它使用图像作为起始模板.

这类似于二进制程序和过程.您在磁盘上有一个二进制程序(例如/bin/sh),当您运行它时,它是您系统上的一个进程.这类似于图像和容器之间的关系.

将图层添加到基本图像

您可以从基本图像构建自己的图像(例如ubuntu在您的示例中).您的一些命令Dockerfile将在最终图像中创建一个新图层.他们有些是RUN,COPYADD.

第一层没有父层.但是每个其他层都有一个父层.通过这种方式,它们相互连接,像煎饼一样堆叠起来.

每个图层都有一个唯一的ID(您已经看到的长十六进制哈希值).它们还可以具有人性化的名称,称为标签(例如ubuntu:16.04).

什么是图层与图像?

从技术上讲,每一层也是一个图像.如果您构建一个新图像并且它有5个图层,则可以使用该图像,它将包含所有5个图层.如果使用堆栈中的第三层作为图像ID运行容器,也可以这样做 - 但它只包含3个图层.你指定的那个和它的祖先是两个.

但是作为惯例,术语"图像"通常表示具有关联标签的层.当你跑步时docker images,它会显示所有顶级图像,并隐藏下面的图层(但你可以用它们全部显示-a).

什么是中间容器?

docker build运行时,它所有的容器内工作(当然!)所以,如果遇到一个RUN步骤,它会创建从当前最上层的容器,请在有指定的命令,然后将结果保存为一个新的图层.然后它将从这个新层创建一个容器,运行下一个...等等.

中间容器仅用于构建过程,并在构建后丢弃.

层文件系统如何工作

您询问是否有人下载ubuntu基于您的图像只是部分下载,如果他们已经在ubuntu本地拥有该图像.

是! 这是完全正确的.

每个图层都使用它下面的图层作为基础.新图层基本上是该图层与新状态之间的差异.但是,它与git提交可能有效的方式不同.它适用于文件级别,而不是行级别.

假设您从一开始ubuntu就运行了这个Dockerfile.

FROM: ubuntu:16.04
RUN groupadd dan && useradd -g dan dan

这将产生两层图像.第一层是ubuntu图像.第二个可能只有少数变化.

/etc/passwd用户"dan"的较新副本

/etc/group包含"dan"组的较新副本

一个新目录 /home/dan

一些默认文件,如 /home/dan/.bashrc

就是这样.如果从此映像启动容器,那么这些文件将位于最顶层,其他所有文件都将来自ubuntu映像中的文件系统.

容器中最顶层的读写层

另一点.运行容器时,可以在文件系统中写入文件.但是,如果您停止容器并从同一图像运行另一个容器,则会重置所有内容.那么文件在哪里写的?

图像是不可变的,因此一旦存在,就无法更改.您可以构建新版本,但这是一个新图像.它将具有不同的ID,并且不会是相同的图像.

容器具有顶层读写层,该层位于图像层之上.任何写入都发生在该层中.它就像其他层一样工作.如果您需要修改文件(或添加一个或删除一个文件),则在顶层完成,不会影响较低层.如果文件已存在,则将其复制到读写层,然后进行修改.这称为写时复制(CoW).

在哪里添加更改

你必须在Dockerfile的底部添加新东西吗?不,你可以在任何地方添加任何东西(或改变任何东西).

但是,由于构建缓存的工作原理,您的工作方式确实会影响构建时间.

Docker将尝试在构建期间缓存结果.如果它通过Dockerfile读取它FROM是相同的,第一个RUN是相同的,第二个RUN是相同的......它将假设它已经完成了这些步骤,并将使用缓存的结果.如果遇到与上一次构建不同的内容,则会使缓存无效.从那时起,一切都将重新焕发新生.

有些事情总是会使缓存失效.例如,如果您使用ADDCOPY,那些总是使缓存无效.那是因为Docker只跟踪构建命令是什么.它没有试图弄清楚"我正在复制与上次相同的文件的这个版本吗?"

所以这是一个常见的做法FROM,然后放置非常静态的东西,比如RUN用例如apt-get等安装软件包的命令.在最初编写Dockerfile之后,这些东西往往不会发生很大的变化.稍后在文件中是一个更方便的地方,可以更频繁地更改内容.

很难简明扼要地提出这方面的建议,因为这实际上取决于所讨论的项目.但是了解构建缓存如何工作并试图利用它是值得的.

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有