与容器共享本地文件
说明
每个容器都包含其运行所需的一切,不依赖于主机上预安装的任何依赖项。由于容器是隔离运行的,它们对主机和其他容器的影响最小。这种隔离有一个主要优势:容器最大程度地减少了与主机系统和其他容器的冲突。然而,这种隔离也意味着容器默认无法直接访问主机上的数据。
考虑这样一种场景:您有一个 Web 应用容器,需要访问存储在主机系统文件中的配置设置。此文件可能包含敏感数据,例如数据库凭据或 API 密钥。将此类敏感信息直接存储在容器镜像中会带来安全风险,尤其是在共享镜像时。为了解决这一挑战,Docker 提供了存储选项,以弥合容器隔离与主机数据之间的差距。
Docker 提供了两种主要的存储选项,用于持久化数据以及在主机与容器之间共享文件:卷(volumes)和绑定挂载(bind mounts)。
卷(Volume)与绑定挂载(Bind Mount)
如果您想确保容器内生成或修改的数据在容器停止运行后仍然保留,则应选择卷。请参阅持久化容器数据了解有关卷及其用例的更多信息。
如果您想将主机系统上的特定文件或目录直接共享给容器,例如配置文件或开发代码,那么您将使用绑定挂载。这就像在主机和容器之间打开一个用于共享的直通门户。绑定挂载非常适合开发环境,在开发环境中,主机和容器之间的实时文件访问和共享至关重要。
在主机与容器之间共享文件
在 docker run
命令中使用的 -v
(或 --volume
)和 --mount
标志都可以让您在本地机器(主机)与 Docker 容器之间共享文件或目录。但是,它们在行为和用法上存在一些关键差异。
-v
标志对于基本的卷或绑定挂载操作来说更简单、更方便。如果使用 -v
或 --volume
时主机位置不存在,则会自动创建一个目录。
想象一下您是一位正在开发项目的开发者。您的开发机器上有一个源代码目录,代码就存放于此。当您编译或构建代码时,生成的 artifact(编译后的代码、可执行文件、镜像等)会保存在源代码目录下的一个单独子目录中。在以下示例中,这个子目录是 /HOST/PATH
。现在您希望这些构建 artifact 能够在一个运行您的应用的 Docker 容器内访问。此外,您希望容器在您每次重新构建代码时都能自动访问最新的构建 artifact。
以下是使用 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 具有访问主机目录所需的权限至关重要。要在创建容器时授予读/写访问权限,您可以使用 -v
或 --mount
标志配合 :ro
(只读)或 :rw
(读写)标志。例如,以下命令授予读写访问权限。
$ 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 Dashboard 删除现有容器
在您的主机系统上创建一个名为
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 Dashboard 上访问文件
您可以通过选择容器的 Files 选项卡,然后选择
/usr/local/apache2/htdocs/
目录中的文件来查看容器内挂载的文件。然后,选择 Open file editor。在主机上删除该文件,并验证该文件是否也在容器中被删除。您会发现 Docker Desktop Dashboard 中 Files 下的文件已不存在。
在主机系统上重新创建 HTML 文件,并查看该文件重新出现在 Docker Desktop Dashboard 的 Containers 下的 Files 选项卡中。现在,您也应该能够访问该站点了。
停止您的容器
容器将一直运行,直到您将其停止。
转到 Docker Desktop Dashboard 中的 Containers 视图。
找到您想要停止的容器。
在 Actions 列中选择 Delete 操作。


更多资源
以下资源将帮助您了解更多关于绑定挂载的信息
下一步
现在您已经了解了如何与容器共享本地文件,接下来是学习多容器应用。