docker如何处理多种安装types?
这篇文章有些简单,但忍受了一段时间…
假设您有一个应用程序位于本地(主机)文件系统的/app
中,其结构如下
app |-- index.php |-- foo | `-- file-h1 `-- bar `-- file-h2
现在假设我们有一个使用以下数据结构的图像(标记为myrepo/app
)
opt |-- app | `-- foo | `-- file-c1
如果我们通过将主机的/app
挂载到容器的/opt/app
来从该映像运行容器,如下所示
docker container run \ -v /app:/opt/app \ myrepo/app
由此产生的容器数据结构如下
opt |-- app | |-- index.php | |-- foo | | `-- file-h1 | `-- bar | `-- file-h2
到现在为止还挺好…
运行具有多个安装的容器(绑定安装和卷)
现在,假设我们要使用一个名为 data
的命名卷 ,将其挂载在/opt/app/vendor
并使用绑定挂载将/app
挂载到/opt/app
docker container run \ -v /app:/opt/app \ -v data:/opt/app/foo myrepo/app
容器内的结果数据结构将是:
opt |-- app | |-- index.php | |-- foo | | `-- file-c1 | `-- bar | `-- file-h2
正如在各种职位(如这个和这个 )中所述,docker坐骑是按字典顺序(即最短path优先)执行的。 据此,我期望docker首先执行bind-mount( -v /app:/opt/app
),然后是卷( -v data:/opt/app/foo
)。
因此,我希望主机/app
的内容将replace/遮盖容器的/opt/app
,从而将file-h1
置于/opt/app/foo
。 最后,将file-h1
复制到新创build的data
卷中,并将卷挂载到/opt/app/foo
(因此应显示file-h1
而不是file-c1
)
我试图在SO上理解这个答案时提出了我的问题
最后,在github用户cpuguy83的帮助下,我想出了docker 引擎在尝试运行一个使用多个不同types的挂载(例如bind-mount和volume )的容器时会做什么 :
docker container run \ -v /app:/opt/app \ -v data:/opt/app/foo myrepo/app
这里要理解的关键是docker以两个步骤执行这个过程,按照以下顺序完成:
-
首先,它在主机文件系统(
... data/
)中为容器创build一个新的存储空间(即容量)来保存文件,然后(由于新创build的卷是空的) 复制容器的文件在/opt/app/foo/*
)到卷的存储位置(... data/
) -
然后在它之后,它按照字典顺序执行所有坐骑(绑定,卷,tmpfs坐骑等等)(首先挂载
/app
到/opt/app
然后... data/
to/opt/app/foo
)
所以,正因为如此,当我们在示例中运行容器时,docker 首先将file-c1
复制到主机文件系统中的... data/
位置,然后首先安装主机/app
到容器的/opt/app
,然后是主机的... data/
(其中包含file-c1
)到容器的/opt/app/foo
覆盖/隐藏其内容(即用file-c1
覆盖file-h1
file-c1
)。 因此,如果我们在完成装载后查看正在运行的容器,结果将如下所示:
opt |-- app | |-- index.php | |-- foo | | `-- file-c1 | `-- bar | `-- file-h2