gpt4 book ai didi

docker - 如何更新 docker 镜像?

转载 作者:IT老高 更新时间:2023-10-28 12:38:38 31 4
gpt4 key购买 nike

我读到 docker 与层一起工作,所以在创建 container 时与 Dockerfile ,您从基础镜像开始,然后运行后续命令向容器添加一个层,因此如果您保存该新容器的状态,您将拥有一个新镜像。对此,我有几件事想知道。

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

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

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

所以它肯定是分块安装的,而不是一次性安装。这些作品是不同的图像吗?

最佳答案

图像与容器
首先,让我澄清一些术语。
图片 : 一个静态的、不可变的对象。这是你运行时构建的东西 docker build使用 Dockerfile .图像不是运行的东西。
图像由层组成。一个图像可能只有一层,也可能有很多层。
容器 : 一个正在运行的东西。它使用图像作为其起始模板。
这类似于二进制程序和进程。您在磁盘上有一个二进制程序(例如 /bin/sh ),当您运行它时,它是您系统上的一个进程。这类似于镜像和容器之间的关系。
将图层添加到基础图像
您可以从基础镜像构建您自己的镜像(例如您的示例中的 ubuntu)。您的 Dockerfile 中的一些命令将在最终图像中创建一个新层。其中一些是 RUN , COPY , 和 ADD .
第一层没有父层。但是每个其他层都会有一个父层。通过这种方式,它们相互连接,像煎饼一样堆叠。
每个层都有一个唯一的 ID(你已经看到的长十六进制哈希)。它们也可以有人性化的名称,称为标签(例如 ubuntu:16.04 )。
什么是图层与图像?
从技术上讲,每一层也是一个图像。如果您构建一个新图像并且它有 5 个层,您可以使用该图像,它将包含所有 5 个层。如果您使用堆栈中的第三层作为图像 ID 运行容器,您也可以这样做 - 但它只会包含 3 层。您指定的一个和作为其祖先的两个。
但作为惯例,术语“图像”通常表示具有关联标签的层。当您运行时 docker images ,它将显示所有顶级图像,并隐藏下面的图层(但您可以使用 -a 显示它们)。
什么是中间容器?
docker build运行时,它会在容器内完成所有工作(很自然!)所以如果遇到 RUN step,它将从当前顶层创建一个容器,在其中运行指定的命令,然后将结果保存为新层。然后它将从这个新层创建一个容器,运行下一件事......等等。
中间容器仅用于构建过程,并在构建后丢弃。
层文件系统如何工作
你问是否有人下载你的ubuntu -based 图像只进行部分下载,如果他们已经有 ubuntu本地镜像。
是的!完全正确。
每一层都使用它下面的层作为基础。新层基本上是该层和新状态之间的差异。不过,这与 git commit 可能工作的方式不同。它适用于文件级别,而不是行级别。
假设您从 ubuntu 开始,然后你运行了这个 Dockerfile。

FROM: ubuntu:16.04
RUN groupadd dan && useradd -g dan dan
这将导致两层图像。第一层将是 ubuntu图片。第二个可能只有少数变化。
  • /etc/passwd 的较新副本与用户“dan”
  • /etc/group 的较新副本与“丹”组
  • 新建目录 /home/dan
  • 几个默认文件,如 /home/dan/.bashrc

  • 就是这样。如果你从这个镜像启动一个容器,那几个文件将位于最顶层,其他所有文件将来自 ubuntu 中的文件系统。图片。
    容器中最顶层的读写层
    还有一点。当您运行容器时,您可以在文件系统中写入文件。但是,如果您停止容器并从同一镜像运行另一个容器,则一切都会重置。那么文件写在哪里呢?
    图像是不可变的,因此一旦创建,就无法更改。您可以构建一个新版本,但那是一个新镜像。它将具有不同的 ID,并且不会是相同的图像。
    容器有一个顶层读写层,它位于镜像层之上。任何写入都发生在该层中。它就像其他层一样工作。如果你需要修改一个文件(或者增加一个,或者删除一个),那是在最上层完成的,不会影响到下层。如果文件已经存在,则将其复制到读写层中,然后进行修改。这称为写时复制 (CoW)。
    在哪里添加更改
    Dockerfile 底部需要添加新的东西吗?不,您可以在任何地方添加任何内容(或更改任何内容)。
    但是,由于构建缓存的工作方式,您做事的方式确实会影响您的构建时间。
    Docker 将尝试在构建期间缓存结果。如果它在读取 Dockerfile 时发现 FROM也是一样,第一个 RUN一样,第二个 RUN是一样的......它会假设它已经完成了这些步骤,并将使用缓存的结果。如果它遇到与上次构建不同的内容,它将使缓存无效。从那时起,一切都将重新运行。
    有些事情总是会使缓存无效。例如,如果您使用 ADDCOPY ,那些总是使缓存无效。那是因为 Docker 只跟踪构建命令是什么。它不会试图弄清楚“我正在复制的文件的这个版本是否与上次相同?”
    所以通常的做法是从 FROM 开始,然后放置非常静态的东西,例如 RUN安装包的命令,例如 apt-get等。在最初编写 Dockerfile 后,这些内容往往不会有太大变化。文件的后面是一个更方便的地方,可以放置更频繁更改的内容。
    很难就此给出好的建议,因为这实际上取决于相关项目。但是了解构建缓存的工作原理并尝试利用它是值得的。

    关于docker - 如何更新 docker 镜像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41603822/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com