【翻译于《Mount Filesystems Within a Docker Container》】
1. 概述
Docker 容器是一个可移植的、轻量级的、隔离的环境,用于运行应用程序及其依赖项。在 Docker 容器中挂载文件系统允许从容器访问主机系统上的文件或目录。这样做对于在容器和主机之间共享数据或配置非常有用。
在本教程中,我们将学习如何在 Docker 容器中挂载文件系统。
2. 主机源目录
首先,要在 Docker 容器中挂载文件系统,必须在系统上安装 Docker。此外,让我们确定主机系统上的源目录,即我们希望在挂载过程中使用的系统上的路径。
为了说明这一点,让我们使用 mkdir 在主机上创建一个新目录:
$ mkdir /home/user1/hostpath
接下来,让我们检查新目录是否存在,并使用 ls 命令验证其属性:
$ ls -ld /home/user1/hostpath/
drwxrwxr-x 2 user1 user1 4096 Jul 17 04:43 /home/user1/hostpath/
在这里,-l
选项启用了目录的长列表,而 -d
标志确保我们显示有关目录文件系统对象的信息,而不是其内容。
准备好源目录后,现在让我们运行容器。
3. 使用卷
为了在 Docker 容器中挂载文件系统,我们在运行容器时使用 -v
或 –volume
标志。它的参数由两个字段组成,用冒号 (:) 分隔:
主机源目录路径
容器目标目录路径
简而言之,我们在使用 docker 时将主机上的目录链接到容器内的目录:
$ docker run -it --rm -v /path/on/host:/path/in/container image_name /bin/bash
让我们分解一下这个命令:
-i
-t
(或 -it
)支持对容器的交互式访问
–rm
在退出时删除容器以释放系统资源(CPU、内存))
/path/on/host 是我们要挂载的主机上目录的路径
/path/in/container 是容器中可访问目录的所需路径
image_name 是我们要运行的 Docker 映像的名称或 ID
/bin/bash 在容器中提供了一个 Bash shell。
重要的是,如果我们不使用 –rm
选项,我们可能需要在退出后手动删除容器以释放存储空间。
4. 运行 Docker 容器
为了说明这一点,现在让我们将上面看到的通用语法中的 /path/on/host 和 /path/in/container 替换为方案的相应源路径和目标路径:
$ docker run -it --rm -v /home/user1/hostpath:/home/cont_path ubuntu /bin/bash
root@e8439d98c634:/#
此命令执行多项操作:
使用 ubuntu 镜像的副本启动一个 Docker 容器
在容器中创建 /home/cont_path 目录
将 /home/cont_path 目标目录映射到我们之前创建的 /home/user1/hostpath 源目录
容器启动并运行后,我们可以通过导航到容器中的目标目录来检查文件系统是否正确挂载:
root@baeldung:/# cd /home/cont_path
root@baeldung:/home/cont_path#
值得注意的是,使用 /home/user1/hostpath 目录,我们现在可以访问容器的 /home/cont_path 目录下任何新生成或修改的数据。Docker 还会复制两条路径之间的任何更改。因此,我们在 /home/cont_path 目录中所做的任何更改都会影响主机和容器系统。为了理解,让我们创建子目录结构 /home/cont_path/dir1/dir2:
# mkdir -p dir1/dir2
退出容器后,让我们检查主机上的目录,看看是否存在添加的内容:
$ ls /home/user1/hostpath/
dir1
$ ls ~/hostpath/dir1
dir2
值得注意的是,当主机目录和容器目录具有相同的内容时,将验证挂载操作是否成功。
5. 使用提升的权限
在 Docker 中,我们可以使用 –privileged
和 –cap
标志在容器中挂载文件系统。
假设我们要设置一个依赖于从主机挂载 CIFS 共享的环境。如果我们尝试直接这样做,容器可能会遇到默认权限不允许挂载的问题。但是,–privileged
和 –cap
可以为容器提供提升的权限。因此,它可以访问主机级资源,包括挂载文件系统。
为了演示,让我们探讨如何使用 –privileged
和 –cap
选项在 Docker 容器中挂载文件系统。
5.1. 使用 –privileged 运行容器
同样,要授予容器提升的权限,我们将使用 –privileged
开关运行它:
$ docker run --privileged -it -v /home/user1/hostpath:/home/cont_path ubuntu /bin/bash
root@53d79f0bb259:/#
为了验证,我们可以使用带有 –format
选项的 docker inspect 命令。此 docker 命令提供有关正在运行的容器的其他数据。重要的是,它可以显示容器是否在特权模式下运行。
因此,让我们使用 –format
标志和容器 ID 作为参数来检查我们的容器是否以提升的权限运行:
$ docker inspect --format='{{.HostConfig.Privileged}}' 22a2439bb82f
true
事实上,true 意味着我们处于特权模式。但是,对于不使用该模式的容器,该命令将打印 false。
5.2. 授予特定权限
为了加强我们对容器功能的控制,我们可以使用 –cap 标志。此选项与 -drop 或 -add 后缀一起使用,以更改 Linux 中容器的默认功能。
值得注意的是,具有较高权限的容器在容器内挂载的文件系统上具有一些默认功能:
- READ
- WRITE
- MKNOD
为了说明如何使用这两个标志,让我们将容器设置为使用除 MKNOD 之外的所有功能:
$ docker run --cap-add=ALL --cap-drop=MKNOD -it -v /home/user1/hostpath:/home/cont_path ubuntu /bin/bash
让我们分解命令中的新标志:
–cap-add=ALL
将所有功能添加到容器中
–cap-drop=MKNOD
删除 MKNOD 功能,从而阻止容器使用 mknod 创建特殊文件
此外,为了让容器执行一些系统管理任务,我们可以赋予它 SYS_ADMIN 功能。为此,我们可以使用 –cap-add=SYS_ADMIN
:
$ docker run --cap-add=SYS_ADMIN -it -v /home/user1/hostpath:/home/cont_path ubuntu /bin/bash
值得注意的是,SYS_ADMIN 参数为容器提供管理权限(如装载权限)。
6. 挂载多个目录
当然,我们可以通过在 docker run 命令中指定多个 -v
标志来挂载多个目录。每个 -v
开关代表一个单独的挂载:
$ docker run -v ~/hostpath/path_A:/home/path_1 -v ~/hostpath/path_B:/home/path_2 image_name
此命令挂载两个目录:
~/hostpath/path_A 到容器中的 /home/path_1
~/hostpath/path_B 到容器中的 /home/path_2
值得注意的是,我们可以通过添加更多的 -v 选项来根据需要挂载任意数量的目录。
为了成功挂载,主机的文件系统必须在容器内可访问。此外,为了确保准确的读写访问,我们可以评估挂载目录的权限和所有权。当我们遇到权限问题时,我们可能需要更改权限或使用其他设置选项。
通常,我们可以毫不费力地在主机和容器之间交换数据和资源。通过在 Docker 容器中挂载文件系统,可以成功进行这种数据交换。此外,它还可以提高灵活性并改善任何容器化应用程序的整体功能。
7. 结论
在本文中,我们了解了如何在 Docker 容器上挂载主机文件系统。首先,我们学习了如何设置主机。然后,我们使用 -v
选项将文件系统挂载到 Docker 容器上。此外,我们以提升的权限将主机文件系统挂载到 Docker 容器上,允许它访问主机级资源。最后,我们测试了文件系统以确认它工作正常。