Mounting Multiple Volumes on a Docker Container – 在Docker容器上挂载多个卷轴

最后修改: 2022年 8月 16日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Docker has multiple options to persist and share data for a running container. However, we may need more than one file storage for a running container, for example, to create backups or grant different access. Or for the same container, we may need to add named volumes and bind them to specific paths.

Docker有多种选择来为运行中的容器持久化和共享数据。然而,我们可能需要为一个正在运行的容器提供一个以上的文件存储,例如,创建备份或授予不同的访问权限。或者对于同一个容器,我们可能需要添加命名的卷,并将其绑定到特定的路径上。

In this tutorial, we’ll see how to mount multiple volumes on a container. We’ll see some examples both with the command line and with Docker Compose.

在本教程中,我们将看到如何在一个容器上装载多个卷。我们将看到一些使用命令行和Docker Compose的例子。

2. Multiple Mounts on a Docker Container

2.一个Docker容器上的多重挂载

Docker uses Storage to persist data, so we are not losing our information if a container restarts. Furthermore, data persistence will be relevant if we want to share in a clustered environment.

Docker使用存储来持久化数据,因此如果容器重新启动,我们的信息就不会丢失。此外,如果我们想在集群环境中进行共享,数据持久性将是相关的。

We’ll create some examples using Volumes and Bind mounts to highlight the most common development use cases.

我们将使用卷轴绑定挂载创建一些示例,以强调最常见的开发用例。

2.1. Using Multiple Volumes

2.1.使用多个卷

First, let’s create two different named volumes:

首先,让我们创建两个不同的命名卷。

docker volume create --name first-volume-data && docker volume create --name second-volume-data

Suppose we want to mount two different volumes for our web application, but one of those paths must be read-only.

假设我们想为我们的网络应用挂载两个不同的卷,但其中一个路径必须是只读的。

If we are using the command line, we can use the -v option:

如果我们使用的是命令行,我们可以使用-v选项。

docker run -d -p 8080:8080 -v first-volume-data:/container-path-1 -v second-volume-data:/container-path-2:ro --name web-app web-app:latest

We can also use anonymous volumes, for example, by including -v container-path. Docker will create it for us, but it gets removed once we delete the container.

我们也可以使用匿名卷,例如,通过包括-v container-path。Docker将为我们创建它,但一旦我们删除容器,它就会被删除。

Let’s inspect our container to check if our mounts are correct:

让我们检查我们的容器,以检查我们的安装是否正确。

docker inspect 0050cda73c6f

We can see relevant information like sources and destinations, types, and also a read-only status for the second volume:

我们可以看到相关的信息,如来源和目的地,类型,还有第二卷的只读状态。

"Mounts": [
  {
      "Type": "volume",
      "Name": "first-volume-data",
      "Source": "/var/lib/docker/volumes/first-volume-data/_data",
      "Destination": "/container-path-1",
      "Driver": "local",
      "Mode": "z",
      "RW": true,
      "Propagation": ""
  },
  {
      "Type": "volume",
      "Name": "second-volume-data",
      "Source": "/var/lib/docker/volumes/second-volume-data/_data",
      "Destination": "/container-path-2",
      "Driver": "local",
      "Mode": "z",
      "RW": false,
      "Propagation": ""
  }
]

Similarly, Docker recommends we use the –mount option:

同样地,Docker建议我们使用-mount选项。

docker run -d \
  --name web-app \
  -p 8080:8080 \
  --mount source=first-volume-data,target=/container-path-1 \
  --mount source=second-volume-data,target=/container-path-2,readonly \
  web-app:latest

The result is the same as the -v option. However, besides better clarity, –mount is the only way we can use volumes with Services when we are in Swarm mode.

其结果与-v选项相同。然而,除了更好的清晰度之外,-mount是我们在服务模式下使用卷的唯一方法。

So, if we want to create a service for our web app which has multiple mounts, we need to use the –mount option:

因此,如果我们想为我们的网络应用创建一个有多个挂载的服务,我们需要使用-mount选项。

docker service create --name web-app-service \
  --replicas 3 \
  --publish published=8080,target=80 \
  --mount source=first-volume-data,target=/container-path-1 \
  --mount source=second-volume-data,target=/container-path-2,readonly \
  web-app

Similarly, we can inspect our service:

同样地,我们可以检查我们的服务。

docker service inspect web-app-service

Likewise, we’ll get some info about the container inside our service specifications:

同样,我们也会在我们的服务规范里面得到一些关于容器的信息。

"Mounts": [
  {
      "Type": "volume",
      "Source": "first-volume-data",
      "Target": "/container-path-1"
  },
  {
      "Type": "volume",
      "Source": "second-volume-data",
      "Target": "/container-path-2",
      "ReadOnly": true
  }
]

2.2. Using Volumes and Bind Mounts

2.2.使用卷和绑定挂载

We may also want to use a volume alongside a mount to a specific folder or file in our host.

我们也可能想使用一个卷来挂载我们主机中的一个特定文件夹或文件。

Suppose we have a MySQL database image, and we need to run an initial script to create a schema or populate it with some data:

假设我们有一个MySQL数据库镜像,并且我们需要运行一个初始脚本来创建一个模式或用一些数据来填充它。

docker run -d \
  --name db \
  -p 3306:3306 \
  --mount source=first-volume-data,target=/var/lib/mysql \
  --mount type=bind,source=/init.sql,target=/docker-entrypoint-initdb.d/init.sql \
  mysql:latest

If we inspect our container, we can now see two different mount types:

如果我们检查我们的容器,我们现在可以看到两种不同的装载类型。

"Mounts": [
  {
      "Type": "volume",
      "Name": "first-volume-data",
      "Source": "/var/lib/docker/volumes/first-volume-data/_data",
      "Destination": "/var/lib/mysql",
      "Driver": "local",
      "Mode": "z",
      "RW": true,
      "Propagation": ""
  },
  {
      "Type": "bind",
      "Source": "/init.sql",
      "Destination": "/docker-entrypoint-initdb.d/init.sql",
      "Mode": "",
      "RW": true,
      "Propagation": "rprivate"
  }
]

2.3. Using Multiple Bind Mounts

2.3.使用多个绑定挂载

Similarly, we can use multiple bind mounts, for example, when we use Localstack, a local AWS emulator.

同样地,我们可以使用多个绑定挂载,例如,当我们使用本地AWS模拟器Localstack时。

Suppose we want to start a local S3 service:

假设我们想启动一个本地S3服务。

docker run --name localstack -d \
  -p 4563-4599:4563-4599 -p 8055:8080 \
  -e SERVICES=s3 -e DEBUG=1 -e DATA_DIR=/tmp/localstack/data \
  -v /.localstack:/var/lib/localstack -v /var/run/docker.sock:/var/run/docker.sock \
  localstack/localstack

While inspecting the container, we see multiple binds in our host configuration:

在检查容器时,我们看到我们的主机配置中有多个绑定。

"Binds": [
  "/.localstack:/var/lib/localstack",
  "/var/run/docker.sock:/var/run/docker.sock"
]

3. Docker Compose

3.Docker Compose

Let’s see a more compact way for multiple mounts with Docker Compose.

让我们看看用Docker Compose来实现多个挂载的更紧凑方式。

3.1. Using Multiple Volumes

3.1.使用多个卷

First, let’s start with two volumes, as shown in our YAML template:

首先,让我们从两个卷开始,如YAML模板中所示。

services:
  my_app:
    image: web-app:latest
    container_name: web-app
    ports:
      - "8080:8080"
    volumes:
      - first-volume-data:/container-path-1
      - second-volume-data:/container-path-2:ro

volumes:
  first-volume-data:
    driver: local
  second-volume-data:
    driver: local

Once we define the volumes we created earlier, we can add the mount in the service in the form of named-volume:container-path.

一旦我们定义了之前创建的卷,我们就可以以named-volume:container-path.的形式在服务中添加挂载。

The Long syntax is also available for Docker Compose, for example:

例如,Docker Compose也可以使用长句法

volumes:
  - type: volume
    source: volume-data
    target: /container-path

3.2. Using Volumes and Bind Mounts

3.2.使用卷和绑定挂载

Again, here’s an example of using a MySQL service:

同样,这里有一个使用MySQL服务的例子。

services:
  mysql-db:
    image: mysql:latest
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_ROOT_HOST=localhost
    ports:
      - '3306:3306'
    volumes:
      - db:/var/lib/mysql
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql

volumes:
  db:
    driver: local

3.3. Using Multiple Bind Mounts

3.3.使用多个绑定挂载

Finally, let’s convert our previous Localstack example to Docker Compose:

最后,让我们把之前的Localstack例子转换为Docker Compose。

services:
  localstack:
    privileged: true
    image: localstack/localstack:latest
    container_name: localstack
    ports:
      - '4563-4599:4563-4599'
      - '8055:8080'
    environment:
      - SERVICES=s3
      - DEBUG=1
      - DATA_DIR=/tmp/localstack/data
    volumes:
      - './.localstack:/var/lib/localstack'
      - '/var/run/docker.sock:/var/run/docker.sock'

4. Conclusion

4.总结

In this article, we’ve seen how to create multiple mounts using Docker.

在这篇文章中,我们已经看到如何使用Docker创建多个挂载。

We’ve seen some combinations of bind mounts and named volumes. We have also seen use cases using the Docker command line and Docker Compose.

我们已经看到了一些绑定挂载和命名卷的组合。我们还看到了使用Docker命令行和Docker Compose的用例。

As always, we can find working code examples over on GitHub.

一如既往,我们可以在GitHub上找到工作代码的例子