我是Docker的新手,我正在努力理解Docker图像到底是什么。Docker映像的每个定义都使用术语“层”,但似乎并没有定义层的含义。
来自Docker官方文档:
我们已经看到Docker镜像是启动Docker容器的只读模板。每张图像都由一系列图层组成。Docker利用联合文件系统将这些层组合成单个映像。联合文件系统允许透明地覆盖独立文件系统(称为分支)的文件和目录,从而形成一个统一的文件系统。
所以我问,什么是层;有人能举几个具体的例子吗?这些图层是如何“合在一起”形成图像的呢?
我是Docker的新手,我正在努力理解Docker图像到底是什么。Docker映像的每个定义都使用术语“层”,但似乎并没有定义层的含义。
来自Docker官方文档:
我们已经看到Docker镜像是启动Docker容器的只读模板。每张图像都由一系列图层组成。Docker利用联合文件系统将这些层组合成单个映像。联合文件系统允许透明地覆盖独立文件系统(称为分支)的文件和目录,从而形成一个统一的文件系统。
所以我问,什么是层;有人能举几个具体的例子吗?这些图层是如何“合在一起”形成图像的呢?
当前回答
根据Docker通过The Moby Project的图像规范:
图像由层组成。每一层都是一组文件系统 的变化。层没有配置元数据,比如环境 变量或默认参数-这些是图像的属性 一个整体,而不是任何特定的层。
因此,从本质上讲,一层只是对文件系统所做的一组更改。
其他回答
自Docker v1.10以来,随着内容可寻址存储的引入,“层”的概念变得非常不同。图层没有图像或属于图像的概念,它们只是可以在图像之间共享的文件和目录的集合。图层和图像被分离。
例如,在一个从基础映像本地构建的映像上,比如说ubuntu:14.04, docker history命令会生成映像链,但是有些映像id会显示为'missing',因为构建历史不再加载。组成这些图像的图层可以通过
docker inspect <image_id> | jq -r '.[].RootFS'
如果存储驱动选择为aufs,则层内容存储在/var/lib/docker/aufs/diff。但是这些层是用一个随机生成的缓存ID命名的,似乎只有出于安全考虑,Docker引擎才知道层和它的缓存ID之间的链接。我还在想办法弄清楚
图像与其构成层之间的对应关系 磁盘上层的实际位置和大小
这个博客提供了很多见解。
我可以给这个问题补充的是,你可以用git作为一个隐喻来理解层、图像和容器的概念。
事情是这样的:
A git repo crossponds to the image. Commit to a git repo crossponds to adding a layer. A git repo is started with git init on another hand an image build starts with the FROM. While you can use multiple FROM in multi stage builds, the concept stays the same since only the last FROM is used. A git repo is updated or based on a series of commits while an image is built by series of command/layers (excepts the CMD) of which each command creates a new layer of the image. Cloning and running a git repo corresponds to starting the container (CMD). Hence when cloning a git repo you typically clone the latest commit, while docker uses the latest created layer of the image when starting(docker run ...)
最后要注意的是,要理解层,很难将其视为一个孤立的概念,而应该将其视为使容器/图像工作的组件或构建块之一。类似地,commit是git版本控制系统的构建块之一,它可以被称为任何东西,而选择commit肯定是有意义的:)。
根据Docker通过The Moby Project的图像规范:
图像由层组成。每一层都是一组文件系统 的变化。层没有配置元数据,比如环境 变量或默认参数-这些是图像的属性 一个整体,而不是任何特定的层。
因此,从本质上讲,一层只是对文件系统所做的一组更改。
docker容器镜像是使用dockerfile创建的。dockerfile中的每一行都将创建一个层。考虑下面的假例子:
FROM ubuntu #This has its own number of layers say "X"
MAINTAINER FOO #This is one layer
RUN mkdir /tmp/foo #This is one layer
RUN apt-get install vim #This is one layer
这将创建一个最终的图像,其中总层数将是X+3
我可能会迟到,但以下是我的看法(补充ashishjain的回答):
基本上,一个层,或图像层是图像或中间图像的变化。你在Dockerfile中指定的每个命令(FROM, RUN, COPY等)都会导致之前的图像发生变化,从而创建一个新层。在使用git时,您可以将其视为阶段性更改:添加一个文件的更改,然后是另一个文件,然后是另一个文件……
考虑下面的Dockerfile:
FROM rails:onbuild
ENV RAILS_ENV production
ENTRYPOINT ["bundle", "exec", "puma"]
首先,我们选择一个起始映像:rails:onbuild,它又有许多层。 我们在开始的图像上添加另一个层,使用ENV命令设置环境变量RAILS_ENV。然后,我们告诉docker运行bundle exec puma(这会启动rails服务器)。这是另一层。
层的概念在构建图像时派上了用场。因为图层是中间图像,如果你对Dockerfile做了更改,docker将只重建被更改的层和之后的层。这被称为层缓存。
你可以在这里阅读更多信息。