与容器共享本地文件

解释

每个容器都拥有其运行所需的一切,不依赖于主机上任何预先安装的依赖项。由于容器在隔离环境中运行,它们对主机和其他容器的影响微乎其微。这种隔离有一个主要好处:容器最大限度地减少了与主机系统和其他容器的冲突。然而,这种隔离也意味着容器默认情况下无法直接访问主机上的数据。

设想一个场景,你有一个 Web 应用程序容器,需要访问存储在主机系统文件中的配置设置。该文件可能包含敏感数据,如数据库凭据或 API 密钥。将此类敏感信息直接存储在容器镜像中会带来安全风险,尤其是在共享镜像时。为了应对这一挑战,Docker 提供了存储选项,以弥合容器隔离与主机数据之间的鸿沟。

Docker 提供了两种主要的存储选项来持久化数据并在主机和容器之间共享文件:卷和绑定挂载。

卷与绑定挂载对比

如果你想确保容器内部生成或修改的数据在容器停止运行后仍然存在,你应该选择卷。请参阅持久化容器数据,了解更多关于卷及其用例的信息。

如果你想将主机系统上的特定文件或目录(如配置文件或开发代码)直接共享给容器,那么你应该使用绑定挂载。这就像在你的主机和容器之间打开一个直接共享的门户。绑定挂载非常适合开发环境,因为在这些环境中,主机和容器之间的实时文件访问和共享至关重要。

在主机和容器之间共享文件

在 `docker run` 命令中使用的 `-v`(或 `--volume`)和 `--mount` 标志都允许你在本地计算机(主机)和 Docker 容器之间共享文件或目录。但是,它们在行为和用法上存在一些关键差异。

对于基本的卷或绑定挂载操作,`-v` 标志更简单、更方便。当使用 `-v` 或 `--volume` 时,如果主机位置不存在,将自动创建一个目录。

想象一下你是一名正在开发项目的开发者。你的开发机器上有一个源代码目录,存放着你的代码。当你编译或构建代码时,生成的工件(编译后的代码、可执行文件、镜像等)会保存在源代码目录下的一个单独子目录中。在以下示例中,此子目录为 `/HOST/PATH`。现在,你希望这些构建工件在运行你的应用程序的 Docker 容器中是可访问的。此外,你还希望每当你重新构建代码时,容器都能自动访问最新的构建工件。

以下是使用 `docker run` 启动一个使用绑定挂载并将其映射到容器文件位置的容器的方法。

$ docker run -v /HOST/PATH:/CONTAINER/PATH -it nginx

`--mount` 标志提供了更高级的功能和更精细的控制,使其适用于复杂的挂载场景或生产部署。如果你使用 `--mount` 来绑定挂载 Docker 主机上尚不存在的文件或目录,`docker run` 命令不会自动为你创建它,而是会生成一个错误。

$ docker run --mount type=bind,source=/HOST/PATH,target=/CONTAINER/PATH,readonly nginx
注意

Docker 建议使用 `--mount` 语法而不是 `-v`。它对挂载过程提供了更好的控制,并避免了因目录丢失而可能出现的问题。

Docker 访问主机文件的文件权限

使用绑定挂载时,确保 Docker 拥有访问主机目录的必要权限至关重要。要授予读/写访问权限,可以在创建容器时使用 `:ro`(只读)或 `:rw`(读写)标志与 `-v` 或 `--mount` 标志一起使用。例如,以下命令授予读写访问权限。

$ docker run -v HOST-DIRECTORY:/CONTAINER-DIRECTORY:rw nginx

只读绑定挂载允许容器访问主机上的挂载文件进行读取,但不能更改或删除这些文件。通过读写绑定挂载,容器可以修改或删除挂载的文件,这些更改或删除也会反映在主机系统上。只读绑定挂载可确保主机上的文件不会被容器意外修改或删除。

同步文件共享

随着你的代码库越来越大,传统的文件共享方法(如绑定挂载)可能会变得效率低下或缓慢,尤其是在需要频繁访问文件的开发环境中。同步文件共享通过利用同步的文件系统缓存来提高绑定挂载的性能。这种优化确保了主机和虚拟机(VM)之间的文件访问既快速又高效。

试一试

在本实践指南中,你将练习如何创建和使用绑定挂载来在主机和容器之间共享文件。

运行一个容器

  1. 下载并安装 Docker Desktop。

  2. 使用以下命令启动一个使用 httpd 镜像的容器。

    $ docker run -d -p 8080:80 --name my_site httpd:2.4
    

    这将在后台启动 `httpd` 服务,并将网页发布到主机的 `8080` 端口。

  3. 打开浏览器并访问 https://:8080,或使用 curl 命令来验证其是否正常工作。

    $ curl localhost:8080
    

使用绑定挂载

通过使用绑定挂载,你可以将主机上的配置文件映射到容器内的特定位置。在此示例中,你将看到如何通过使用绑定挂载来更改网页的外观和感觉。

  1. 使用 Docker Desktop Dashboard 删除现有容器

    A screenshot of Docker Desktop Dashboard showing how to delete the httpd container
  2. 在您的主机系统上创建一个名为 `public_html` 的新目录。

    $ mkdir public_html
    
  3. 进入新创建的 `public_html` 目录,并创建一个名为 `index.html` 的文件,内容如下。这是一个基本的 HTML 文档,创建了一个简单的网页,用一只友好的鲸鱼欢迎您。

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title> My Website with a Whale & Docker!</title>
    </head>
    <body>
    <h1>Whalecome!!</h1>
    <p>Look! There's a friendly whale greeting you!</p>
    <pre id="docker-art">
       ##         .
      ## ## ##        ==
     ## ## ## ## ##    ===
     /"""""""""""""""""\___/ ===
    {                       /  ===-
    \______ O           __/
    \    \         __/
     \____\_______/
    
    Hello from Docker!
    </pre>
    </body>
    </html>
  4. 现在是时候运行容器了。`--mount` 和 `-v` 示例产生相同的结果。除非在运行第一个容器后移除 `my_site` 容器,否则您不能同时运行它们。

    $ docker run -d --name my_site -p 8080:80 -v .:/usr/local/apache2/htdocs/ httpd:2.4
    
    $ docker run -d --name my_site -p 8080:80 --mount type=bind,source=./,target=/usr/local/apache2/htdocs/ httpd:2.4
    
    提示

    在 Windows PowerShell 中使用 `-v` 或 `--mount` 标志时,您需要提供目录的绝对路径,而不仅仅是 `./`。这是因为 PowerShell 处理相对路径的方式与 bash(在 Mac 和 Linux 环境中常用)不同。

    现在一切都已启动并运行,您应该能够通过 https://:8080 访问该网站,并发现一个用友好的鲸鱼欢迎您的新网页。

在 Docker Desktop Dashboard 中访问文件

  1. 您可以通过选择容器的**文件**选项卡,然后在 `/usr/local/apache2/htdocs/` 目录内选择一个文件来查看容器内挂载的文件。然后,选择**打开文件编辑器**。

    A screenshot of Docker Desktop Dashboard showing the mounted files inside the a container
  2. 在主机上删除该文件,并验证该文件在容器中也已被删除。您会发现该文件在 Docker Desktop Dashboard 的**文件**下已不存在。

    A screenshot of Docker Desktop Dashboard showing the deleted files inside the a container
  3. 在主机系统上重新创建 HTML 文件,可以看到该文件在 Docker Desktop Dashboard 的**容器**下的**文件**选项卡中重新出现。此时,您应该也能访问该网站了。

停止你的容器

容器将继续运行,直到您停止它。

  1. 转到 Docker Desktop Dashboard 中的**容器**视图。

  2. 找到您想要停止的容器。

  3. 在“操作”列中选择**删除**操作。

A screenshot of Docker Desktop Dashboard showing how to delete the container

其他资源

以下资源将帮助您了解更多关于绑定挂载的信息

后续步骤

现在您已经了解了如何与容器共享本地文件,是时候学习多容器应用程序了。

多容器应用程序
© . This site is unofficial and not affiliated with Kubernetes or Docker Inc.