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-mountvolume )的容器时会做什么

 docker container run \ -v /app:/opt/app \ -v data:/opt/app/foo myrepo/app 

这里要理解的关键是docker以两个步骤执行这个过程,按照以下顺序完成:

  1. 首先,它在主机文件系统( ... data/ )中为容器创build一个新的存储空间(即容量)来保存文件,然后(由于新创build的卷是空的) 复制容器的文件在/opt/app/foo/* )到卷的存储位置( ... data/

  2. 然后在它之后,它按照字典顺序执行所有坐骑(绑定,卷,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