与容器共享本地文件
解释
每个容器都拥有其运行所需的一切,不依赖于主机上任何预安装的依赖项。由于容器在隔离环境中运行,它们对主机和其他容器的影响极小。这种隔离有一个主要的好处:容器最大限度地减少了与主机系统和其他容器的冲突。然而,这种隔离也意味着容器默认情况下无法直接访问主机上的数据。
考虑一个场景,您有一个需要访问存储在主机系统上的配置文件中的配置设置的Web应用程序容器。该文件可能包含敏感数据,如数据库凭据或API密钥。将此类敏感信息直接存储在容器镜像中会带来安全风险,特别是在镜像共享期间。为了解决这一挑战,Docker提供了存储选项,以弥合容器隔离与主机数据之间的差距。
Docker 提供了两种主要的存储选项,用于在主机和容器之间持久化数据和共享文件:卷和绑定挂载。
Volume 与 bind mounts 的比较
如果你想确保容器内生成或修改的数据在容器停止运行后仍然保留,你会选择使用卷。参见 持久化容器数据以了解更多关于卷及其使用场景的信息。
如果您在主机系统上有特定的文件或目录想要直接与容器共享,比如配置文件或开发代码,那么您可以使用绑定挂载。这就像在主机和容器之间打开了一个直接的门户,用于共享。绑定挂载非常适合开发环境,其中主机和容器之间的实时文件访问和共享至关重要。
在主机和容器之间共享文件
无论是 -v(或 --volume)还是 --mount 标志,与 docker run 命令一起使用时,都可以让你在本地机器(主机)和 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)之间的文件访问快速且高效。
试试看
在本实践指南中,您将练习如何创建和使用绑定挂载来在主机和容器之间共享文件。
运行一个容器
下载并安装 Docker Desktop。
使用以下命令启动一个容器,使用 httpd 镜像:
$ docker run -d -p 8080:80 --name my_site httpd:2.4这将在后台启动
httpd服务,并将网页发布到主机的8080端口。打开浏览器并访问 http://localhost:8080 或使用curl命令来验证它是否正常工作。
$ curl localhost:8080
使用绑定挂载
使用绑定挂载,您可以将主机上的配置文件映射到容器内的特定位置。在这个示例中,您将看到如何通过使用绑定挂载来更改网页的外观和感觉:
使用 Docker Desktop 仪表板删除现有容器:

在您的主机系统上创建一个名为
public_html的新目录。$ mkdir public_html将目录更改为
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>是时候运行容器了。
--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访问该网站,并找到一个友好的鲸鱼欢迎您的新网页。
在 Docker Desktop 仪表板上访问文件
您可以通过选择容器的文件选项卡,然后在
/usr/local/apache2/htdocs/目录中选择一个文件来查看容器内挂载的文件。然后,选择打开文件编辑器。

删除主机上的文件并验证该文件在容器中是否也被删除。您会发现文件在Docker Desktop仪表板的文件下不再存在。

在主机系统上重新创建HTML文件,并查看该文件是否重新出现在Docker Desktop仪表板上容器下的文件选项卡中。此时,您也将能够访问该站点。
停止你的容器
容器会一直运行,直到你停止它。
前往 Docker Desktop 仪表板中的容器视图。
找到您想要停止的容器。
在操作列中选择删除操作。

其他资源
以下资源将帮助您了解更多关于绑定挂载的信息:
下一步
既然你已经学习了如何与容器共享本地文件,现在是时候学习多容器应用程序了。