# bind mounts

从docker早期开始，bind mounts就一直存在。与卷相比，bind mounts的功能有限。当使用bind mount时，主机上的文件或目录将被挂载到容器中。主机上的文件或目录通过绝对路径被引用。相比之下，当使用卷时，在主机上的 Docker存储目录中创建了一个新的目录，Docker 管理该目录的内容 。

文件或目录不需要已经存在于Docker主机上。如果它们还不存在，则会按需创建。bind mount性能很好，但它们依赖于主机上面具有可用的特定目录结构的文件系统。如果我们正在开发新的Docker应用程序，请考虑使用命名卷。我们无法使用Docker CLI命令直接管理bind mounts。

![](/files/-MWZDl0hnp9ffXHGVoqg)

### 选择-v还是--mount

通常来说，`--mount`更加的明确和详细。最大的不同是`-v`语法将所有的选项组合在一起放入一个字段，而`--mount`语法则是分开的。

{% hint style="info" %}
新用户应该使用--mount语法，有经验的用户可能更熟悉-v或--volume语法，但是依然鼓励使用--mount，因为它更容易被使用。
{% endhint %}

`-v`或`--volume`: 由三个字段组成，通过:分隔开。字段必须按照正确的顺序组合。

* 在使用bind mounts时，第一个字段是主机上面的文件或目录路径。
* 第二个字段指定容器中被挂载的文件或路径。
* 第三个字段是可选的，是一个逗号分隔的选项列表，例如`ro, z, Z`。

`--mount`：由多个键值对组成，通过逗号进行分隔，每一个都是一个键值对组合。`--mount`语法比`-v`或`--volume`更详细，但是键的顺序没有那么重要，并且它所对应的值更容易被理解。

* 挂载的类型`(type)`可以是`bind`，`volume`或者`tmpfs`。
* 挂载的源`(source)`。对于命名卷，它是卷的名称。对于bind mounts，这是Docker主机上的文件或目录路径。可以通过`source`或`src`两种形式来指定源。
* 挂载的目的地`(destination)`使用容器中被挂载的文件或目录的路径作为值。可以通过`destination`，`dst`或`target`三种形式来指定目的地。
* `readonly`选项如果存在，它会将`bind mountbind`以只读的形式挂载到容器中。
* bind-propagation选项，如果存在，它会修改bind propagation。可能是rprivate，private，rshared，shared，rslave，slave中的一个。
* \--mount不支持使用z或Z选项来修改selinux标签。

### &#x20;--v和--mount的区别

如果使用-v或--volume bind mount一个文件或目录时，如果Docker主机上面不存在该文件或目录，则-v选项总是会为我们以目录的形式创建该文件。

如果使用--mount来bind mount一个文件或目录时，如果Docker主机上面不存在该文件或目录，则--mount不会为我们自动创建这些文件，通常会产生一个错误。

### 通过bind mount启动一个容器

考虑这样一个使用场景，我们有一个目录source，当我们构建源码时，我们将构建好的代码存入source下面的source/target目录。我们希望target目录下面的代码可以在docker中的/app目录下面被使用。并且希望每次构建代码时，容器都可以访问。我们使用下面的命令:

{% tabs %}
{% tab title="--mount" %}

```
$ docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app \
  nginx:latest
```

{% endtab %}

{% tab title="-v" %}

```
$ docker run -d \
  -it \
  --name devtest \
  -v "$(pwd)"/target:/app \
  nginx:latest
```

{% endtab %}
{% endtabs %}

使用docker inspect devtest来检查bind mount创建是否正确，查看Mounts部分：

```
"Mounts": [
    {
        "Type": "bind",
        "Source": "/tmp/source/target",
        "Destination": "/app",
        "Mode": "",
        "RW": true,
        "Propagation": "rprivate"
    }
],
```

上面的信息正确显示了挂载类型为bind挂载，源和目标都是正确的。

停止容器：

```
$ docker container stop devtest

$ docker container rm devtest
```

### 挂载到一个容器中的非空目录

如果bind-mount挂载到了容器中的一个非空目录，目录已经存在的内容会被bind mount遮蔽。这是有好处的，例如你想测试一个新版本的应用而不构建一个新的镜像。

下面的示例使用/tmp目录中的内容替代了/usr/中的内容。大部分情况下，这将导致一个非功能化的容器。

{% tabs %}
{% tab title="--mount" %}

```
$ docker run -d \
  -it \
  --name broken-container \
  --mount type=bind,source=/tmp,target=/usr \
  nginx:latest

docker: Error response from daemon: oci runtime error: container_linux.go:262:
starting container process caused "exec: \"nginx\": executable file not found in $PATH".
```

{% endtab %}

{% tab title="-v" %}

```
$ docker run -d \
  -it \
  --name broken-container \
  -v /tmp:/usr \
  nginx:latest

docker: Error response from daemon: oci runtime error: container_linux.go:262:
starting container process caused "exec: \"nginx\": executable file not found in $PATH".
```

{% endtab %}
{% endtabs %}

上面的命令创建了容器但是没有成功启动，删除失败的容器：

```
$ docker container rm broken-container
```

### 使用只读bind mount

对于一些应用的开发，容器需要写入到bind mount，但是这个更改会蔓延到docker主机上面。在其他时间，容器只需要只读权限。

下面的示例修改了上面的命令，但是以只读的形式通过bind mount挂载目录。只需要在选项的末尾添加ro选项。选项之间通过逗号分隔。

{% tabs %}
{% tab title="--mount" %}

```
$ docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source="$(pwd)"/target,target=/app,readonly \
  nginx:latest
```

{% endtab %}

{% tab title="-v" %}

```
$ docker run -d \
  -it \
  --name devtest \
  -v "$(pwd)"/target:/app:ro \
  nginx:latest
```

{% endtab %}
{% endtabs %}

使用docker inspect devtest来检查创建的bind mount是否正确。查看Mounts部分：

```
"Mounts": [
    {
        "Type": "bind",
        "Source": "/tmp/source/target",
        "Destination": "/app",
        "Mode": "ro",
        "RW": false,
        "Propagation": "rprivate"
    }
],
```

停止容器:

```
$ docker container stop devtest

$ docker container rm devtest
```

### 配置selinux标签

如果想要使用selinux，可以添加z或Z选项来修改被挂载到容器中的主机文件或目录的selinux标签。这会影响主机上面的文件或目录本身并且在Docker的外部作用域依然有效。

* z选项表示bind mount内容在多个容器中共享。
* Z选项表示bind mount的内容是是私有和不可共享的。

使用这些选项时要格外小心。将系统目录(如/home或/usr与Z选项绑定)使主机无法操作，我们可能需要手工重新标记主机文件。

下面的示例设置了z选项来指定多个容器可以共享bind mount的内容：

无法使用--mount来修改selinux标签。

```
$ docker run -d \
  -it \
  --name devtest \
  -v "$(pwd)"/target:/app:z \
  nginx:latest
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://camelgemonion.gitbook.io/docker/docker-overview/docker-cun-chu/bind-mounts.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
