与容器共享本地文件

说明

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

考虑这样一个场景:你有一个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. 打开浏览器并访问 http://localhost:8080 或使用 curl 命令验证其是否正常工作。

    $ curl localhost:8080
    

使用绑定挂载

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

  1. 使用 Docker Desktop 仪表板删除现有容器:

    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 文档,它创建了一个简单的网页,用友好的鲸fish欢迎你。

    <!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 环境中使用)不同。

    现在一切都已启动并运行,您应该能够通过 http://localhost:8080 访问该站点,并找到一个欢迎您的友好鲸fish的新网页。

在 Docker Desktop 仪表板上访问文件

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

    A screenshot of Docker Desktop Dashboard showing the mounted files inside the a container
  2. 删除主机上的文件并验证容器中的文件是否也被删除。您将发现文件在 Docker Desktop 仪表板的文件下不再存在。

    A screenshot of Docker Desktop Dashboard showing the deleted files inside the a container
  3. 在主机系统上重新创建HTML文件,并查看该文件是否在Docker Desktop仪表板的容器下的文件选项卡中重新出现。此时,您应该能够访问该站点了。

停止您的容器

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

  1. 前往 Docker Desktop 仪表板中的 容器 视图。

  2. 定位您想要停止的容器。

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

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

其他资源

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

后续步骤

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