Mounting a Single File in a Volume Using Docker – 使用Docker挂载卷中的单个文件

最后修改: 2022年 7月 25日

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

1. Overview

1.概述

As we know, we can containerize our applications using Docker, making software delivery easier. Besides embedding only our app, we can extend the target containers using various options, e.g., mounting external files.

正如我们所知,我们可以使用Docker对我们的应用程序进行容器化,使软件交付更加容易。除了只嵌入我们的应用程序,我们还可以使用各种选项来扩展目标容器,例如,挂载外部文件。

In this tutorial, we’ll focus on mounting a single file using Docker, showing different ways to do that. Moreover, we’ll discuss common mistakes during the process and how to fix them.

在本教程中,我们将专注于使用Docker挂载单个文件,展示不同的方法。此外,我们将讨论该过程中的常见错误以及如何解决这些问题。

2. Persisting Data in Docker

2.在Docker中持久化数据

Before we move on, let’s make a quick recap of how Docker manages application data.

在我们继续之前,让我们对Docker如何管理应用数据做一个简单的回顾。

We know that Docker creates an isolated environment for every running container. By default, files are stored on an internal container’s writable layer. This means that any changes done inside the container will be lost when it no longer exists.

我们知道,Docker为每个正在运行的容器创建了一个隔离的环境。默认情况下,文件被存储在内部容器的可写层上。这意味着在容器内所做的任何改变在它不再存在时都会丢失

To prevent data loss, Docker provides two main mechanisms for persisting our files to host machines: volumes and bind mounts.

为了防止数据丢失,Docker提供了两种主要的机制来将我们的文件持久化到主机上。卷轴绑定挂载

Volumes are created and managed by Docker itself, and external processes shouldn’t modify them. On the other hand, bind mounts may be stored and managed by the host system without preventing non-Docker processes from editing the data.

卷是由Docker本身创建和管理的,外部进程不应该修改它们。另一方面,绑定挂载可以由主机系统存储和管理,而不会阻止非Docker进程编辑数据。

To achieve our goal, we’ll focus on the binding mechanism.

为了实现我们的目标,我们将专注于绑定机制。

3. Binding Files Using Docker CLI

3.使用Docker CLI绑定文件

The easiest way to interact with Docker is to use a dedicated Docker CLI that executes various commands with configuration flags. As we know, to create a single container, we can use the docker run command with the desired image:

与Docker交互的最简单方法是使用专门的Docker CLI,它可以执行带有配置标志的各种命令。正如我们所知,要创建一个单一的容器,我们可以使用docker run命令和所需的镜像。

docker run alpine:latest

According to the official reference, the run command supports many additional options that allow preconfiguring the container. Let’s look through the list of available options:

根据官方参考资料run命令支持许多额外的选项,可以预先配置容器。让我们看一下可用选项的列表。

--mount		        Attach a filesystem mount to the container
--volume , -v		Bind mount a volume

Both work similarly, allowing us to persist the data locally. Now let’s look at each of them.

这两个工作方式类似,允许我们将数据持久化在本地。现在让我们来看看它们各自的情况。

3.1. –mount Option

3.1.-mount 选项

The syntax of the –mount option consists of multiple key-value pairs, using <key>=<value> tuples. The order of the keys is not significant, separating multiple pairs by commas.

-mount选项的语法由多个键值对组成,使用<key>=<value>图元。键的顺序并不重要,用逗号分隔多个对。

First, let’s create a dummy file in our working directory:

首先,让我们在我们的工作目录中创建一个假文件。

$ echo 'Hi Baeldung! >> file.txt

To mount a single local file to the container, we can extend the previous run command:

为了向容器挂载单个本地文件,我们可以扩展之前的run命令。

$ docker run -d -it \
   --mount type=bind,source="$(pwd)"/file.txt,target=/file.txt,readonly \
   alpine:latest

We’ve just created and started a new container mounting our local file. Let’s now take a look at the configuration keys.

我们刚刚创建并启动了一个新的容器,装载了我们的本地文件。现在让我们看一下配置键。

The type specifies the mounting mechanism with available values: bind, volume, or tmpfs. In our case, we should always set a value to bind.

类型指定安装机制,可用的值。bind, volume,tmpfs。在我们的例子中,我们应该总是设置一个值为bind

The source (alternatively – src) is the absolute path to the file or directory on the host that should be mounted. We can also use local shell commands to calculate the result.

source(或者 – src)是主机上应该被挂载的文件或目录的绝对路径。我们也可以使用本地shell命令来计算结果。

The target (alternatively – destination, dst) takes the absolute path where the file or directory is mounted inside the container.

target(或者说- destination,dst)采取文件或目录在容器中被挂载的绝对路径。

Finally, there’s also a readonly option which makes the bind mount read-only. This flag is optional.

最后,还有一个readonly选项,使绑定挂载成为只读。这个标志是可选的。

In the end, let’s verify the mounting result:

最后,让我们来验证一下安装的结果。

$ docker exec ... cat /file.txt
Hi Baeldung!

We can also inspect container details, using the docker inspect command to check all mounts:

我们还可以检查容器的细节,使用docker inspect命令来检查所有的挂载。

"Mounts": [
    {
        "Type": "bind",
        "Source": ".../file.txt",
        "Destination": "/file.txt",
        "Mode": "",
        "RW": false,
        "Propagation": "rprivate"
    }
],

Now, we can look at common mistakes related to paths. If we provide non-absolute paths, Docker CLI will return an error that terminates the command execution:

现在,我们可以看看与路径有关的常见错误。如果我们提供非绝对路径,Docker CLI将返回一个错误,终止命令执行。

docker: Error response from daemon: invalid mount config for type "bind": invalid mount path: 'file.txt+' mount path must be absolute.

Sometimes we provide an absolute source path to a file missing on the host machine. In this case, the container will start mounting an empty directory in the target path. Moreover, if we are working on Windows, we should take care of the path conversions.

有时我们会提供一个在主机上丢失的文件的绝对源路径。在这种情况下,容器将开始在目标路径中挂载一个空目录。此外,如果我们在Windows上工作,我们应该照顾到路径的转换

3.2. –volume Option

3.2.-volume 选项

As we mentioned earlier, we can replace –mount and–volume (–v) flags with the same functionality. We must also remember that the syntax is completely different.

正如我们前面提到的,我们可以用相同的功能替换-mount-volume-v)flags。我们还必须记住,其语法是完全不同的。

The –volume syntax consists of three fields, separated by colon characters. Moreover, the order of the values is significant.

-体积语法包括三个字段,用冒号字符分开。此外,值的顺序是重要的

Let’s transform the previous example by using the –v option:

让我们通过使用-v选项来转换前面的例子。

$ docker run -d -it
    -v "$(pwd)"/file.txt:/file.txt:ro \
    alpine:latest

The result is the same. We’ve just mounted our local file to the container.

其结果是一样的。我们刚刚把我们的本地文件挂载到容器中。

As we can see, three values given by the –v option are similar to the keys used with the –mount flag.

我们可以看到,由-v选项给出的三个值与-mount标志使用的键相似。

The first value, like the source key, specifies the path to a file or directory on the host machine.

第一个值,像source键一样,指定主机上的文件或目录的路径。

The second field provides a path inside the container and the target key.

第二个字段提供了容器内的路径和target键。

Finally, we have an optional ro option that specifies the read-only attribute.

最后,我们有一个可选的ro选项,指定只读属性。

After we check the syntax, let’s see some common mistakes. Same as before, we should remember about Windows path separators. Selecting a non-existent file will also result in creating an empty directory.

在我们检查完语法后,让我们看看一些常见的错误。和以前一样,我们应该记住Windows路径分隔符选择一个不存在的文件也会导致创建一个空目录

But there is a slight difference with non-absolute paths. If we provide an invalid path to the second value, same as previously, Docker CLI will return an error. However, if we provide such a path as a source value, the Docker will create a named volume which is another mechanism of persisting files.

但在非绝对路径方面有一点不同。如果我们提供一个无效的路径的第二个值,与之前一样,Docker CLI将返回一个错误。然而,如果我们提供这样一个路径作为源值,Docker将创建一个命名的卷,这是另一种持久化文件的机制。

In summary, the most significant difference between the –mount and –volume flags is their syntax. We can use both of them interchangeably.

总之,-mount-volume标志之间最显著的区别是它们的语法。我们可以互换地使用它们。

4. Binding Files Using Docker Compose

4.使用Docker Compose绑定文件

After we learned how to bind files using the Docker CLI, let’s now check if we can still get the same result with docker-compose files.

在我们学会了如何使用Docker CLI绑定文件之后,现在让我们检查一下,我们是否还能用docker-compose文件获得同样的结果。

As we know, docker-compose is a convenient way of creating containers by providing configuration files. For each service, we can declare a volumes section to configure binding options. The volumes section can be specified using either the long syntax or the short one, which has lots in common with –mount and –volumes flags, respectively.

正如我们所知,docker-compose是一种通过提供配置文件创建容器的便捷方式。对于每个服务,我们可以声明一个volumes部分来配置绑定选项volumes部分可以使用长语法或短语法来指定,这与-mount-volumes标志有很多共同之处。

4.1. Long Syntax

4.1.长句法

The long syntax allows us to configure each key separately to specify the volume mount. With the same example, let’s prepare a docker-compose entry:

长的语法允许我们分别配置每个键来指定卷装载。用同样的例子,让我们准备一个docker-compose条目。

services:
  alpine:
    image: alpine:latest
    tty: true
    volumes:
      - type: bind
        source: ./file.txt
        target: file.txt
        read_only: true

Same as with the Docker CLI, our container is now preconfigured to mount a local file in it. We use typesourcetarget, and the optional read_only keys to determine the configuration, just like we use the –mount flag. Additionally, we can use a relative path as the source value, calculated from the docker-compose file.

与Docker CLI一样,我们的容器现在已经被预设为在其中挂载一个本地文件。我们使用typesourcetarget和可选的read_only键来确定配置,就像我们使用-mount标志一样。此外,我们可以使用一个相对路径作为source值,从docker-compose文件中计算出来。

4.2. Short Syntax

4.2.短语法

The short syntax uses a single string value separated by colons to specify a volume mount:

简短的语法使用一个单一的字符串值 用冒号隔开来指定一个卷挂载

services:
  alpine:
    image: alpine:latest
    tty: true
    volumes:
      - ./file.txt:/file.txt:ro

The string is almost the same as the –volume flag. The first two values represent the source and target paths, respectively. The last part specifies additional flags, where we can specify the read-only attribute. As with the long syntax, we can also use a relative source path.

这个字符串与-volume标志几乎相同。前两个值分别代表源和目标路径。最后一部分指定额外的标志,在这里我们可以指定只读的属性。与长句法一样,我们也可以使用相对源路径。

We must remember that the long form allows us to configure additional fields that can’t be expressed in the short syntax. Moreover, we can mix both syntaxes in the single volumes section.

我们必须记住,长格式允许我们配置不能用短语法表达的额外字段。此外,我们可以在单一的volumes部分混合两种语法。

5. Conclusion

5.总结

In this article, we’ve just covered a part of data persistence in Docker. We tried to mount a single local file in a container using both the Docker CLI and docker-compose files.

在这篇文章中,我们刚刚介绍了Docker中数据持久性的一部分。我们尝试使用Docker CLI和docker-compose文件在容器中挂载一个本地文件。

The Docker CLI provides the –mount and –volume options with a run command to bind a single file or directory. Both flags work similarly but have different syntaxes. As a result, we can use them interchangeably.

Docker CLI提供了-mount -volume 选项,通过run 命令来绑定单个文件或目录。这两个标志的工作原理相似,但有不同的语法。因此,我们可以互换使用它们。

We can also reach the same result using docker-compose files. Inside the volumes section for each service, we can configure a volume mount using either a long or short syntax. Same as before, these syntaxes interchangeably produce the same result.

我们也可以使用docker-compose文件达到同样的结果。在每个服务的volumes部分,我们可以使用长或短的语法来配置卷装载。和以前一样,这些语法可以互换产生相同的结果。