这篇文章有点长篇大论但是我已经有一段时间了...
假设您的本地(主机)文件系统中的应用程序位于/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
和 bind-mount 将/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
正如在各个帖子(如this和this中所述)中所述的码头工人坐骑是按照字典顺序执行的(即最短路径优先)。根据这个,我希望docker首先执行bind-mount(-v /app:/opt/app
)然后执行卷(-v data:/opt/app/foo
)。
因此,我希望期待主持人/app
的内容会替换/隐藏容器/opt/app
的内容,从而file-h1
1}}在/opt/app/foo
内。最后,file-h1
在新创建的data
卷中为copied,并且卷将挂载在/opt/app/foo
上(因此应显示file-h1
而不是{{} 1}})
当我尝试理解this回答SO
时,我提出了一些问题答案 0 :(得分:8)
最后,在github用户cpuguy83的帮助下,我想出当我们尝试运行使用多个不同类型的挂载的容器时,实际上docker引擎会做什么(例如,两者都是<例如:strong> bind-mount 和卷):
docker container run \
-v /app:/opt/app \
-v data:/opt/app/foo
myrepo/app
这里要理解的关键点是,docker按照以下顺序执行两步中的过程:
首先,它在主机文件系统(... data/
)中创建一个新的存储空间(即卷),以便容器保存文件,然后(因为新创建的卷为空)它{{ 3}}容器的文件(即/opt/app/foo/*
内的任何内容)到卷的存储位置(... data/
)
然后,它按字典顺序执行所有安装(绑定,卷,tmpfs挂载等等都被集中在一起)(先挂载/app
到/opt/app
然后{ {1}}至... data/
)
因此,正因为如此,当我们在示例中运行带有挂载的容器时,docker first 会将/opt/app/foo
复制到主机中的file-c1
位置文件系统和第二它首先将主机... data/
的内容挂载到容器的/app
,然后将主机的/opt/app
(包含... data/
)挂载到容器的file-c1
覆盖/遮盖其内容(即用/opt/app/foo
覆盖file-h1
)。因此,如果我们在完成安装后查看正在运行的容器内部,结果将如下:
file-c1