docker如何处理多种装载类型?

docker如何处理多种装载类型?,docker,docker-compose,Docker,Docker Compose,这篇文章有点长,但请容忍我一段时间 假设您有一个应用程序位于本地(主机)文件系统中的/app,其结构如下 app |-- index.php |-- foo | `-- file-h1 `-- bar `-- file-h2 opt |-- app | `-- foo | `-- file-c1 现在假设我们有一个图像(标记为myrepo/app),它利用了以下数据结构 app |-- index.php |-- foo | `-- file-h1 `-- b

这篇文章有点长,但请容忍我一段时间

假设您有一个应用程序位于本地(主机)文件系统中的
/app
,其结构如下

app
|-- index.php
|-- foo
|   `-- file-h1
`-- bar
    `-- file-h2
opt
|-- app
|   `-- foo
|       `-- file-c1
现在假设我们有一个图像(标记为
myrepo/app
),它利用了以下数据结构

app
|-- index.php
|-- foo
|   `-- file-h1
`-- bar
    `-- file-h2
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 
到目前为止,一切都很好

正在运行具有多个装载(绑定装载和卷)的容器 现在,让我们假设我们想使用
/opt/app/vendor
装载到
/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挂载按字典顺序执行(即最短路径优先)。根据这一点,我希望docker首先执行绑定装载(
-v/app:/opt/app
),然后执行卷(
-v data:/opt/app/foo

因此,我希望主机的
/app
的内容将替换/隐藏容器的
/opt/app
的内容,从而
文件-h1
位于
/opt/app/foo
内。最后,
file-h1
将位于新创建的
data
卷中,该卷将装入
/opt/app/foo
(因此应显示
file-h1
,而不是
file-c1


最后,在github用户的大量帮助下,当我尝试运行一个使用多个不同类型挂载(例如绑定挂载和卷挂载)的容器时,我发现docker引擎实际上做了什么,例如:

docker container run \
-v /app:/opt/app \
-v data:/opt/app/foo
myrepo/app
这里需要理解的关键点是docker按照以下顺序执行两个步骤:

  • 首先,它在主机文件系统(
    …data/
    )中为容器创建一个新的存储空间(即卷)以保存文件,然后(因为新创建的卷是空的)将容器的文件(即
    /opt/app/foo/*
    )保存到卷的存储位置(
    …data/

  • 然后,它按照字典顺序执行所有装载(绑定、卷、tmpfs装载等…都集中在一起)(首先装载
    /app
    /opt/app
    ,然后装载
    …数据/
    /opt/app/foo

  • 因此,正因为如此,当我们在示例中运行带有挂载的容器时,docker首先将
    文件-c1
    复制到
    。。。数据/
    在主机文件系统中的位置,然后它将首先将主机的
    /app
    的内容装载到容器的
    /opt/app
    ,然后装载主机的
    。。。数据/
    (包含
    file-c1
    )到容器的
    /opt/app/foo
    覆盖/隐藏其内容(即用
    file-c1
    覆盖
    file-h1
    )。因此,如果我们在装载完成后查看正在运行的容器内部,结果将如下所示:

    opt
    |-- app
    |   |-- index.php
    |   |-- foo       
    |   |   `-- file-c1          
    |   `-- bar
    |       `-- file-h2
    

    这是一件非常特别的事情,我正要问你,然后我遇到了你的问题,它正好解释了我想要什么!我注意到了完全相同的行为,不知道为什么。谢谢!