在Docker中混合使用命名卷和绑定挂载?

23
命名卷绑定挂载点如何混合使用?如果使用以下设置,那么在绑定挂载点中存在的路径是否仍然可用于绑定挂载点内部? /var/www/html/wp-content/uploads 使用单独的容器并将其附加到命名卷似乎表明这不是情况,因为在单独容器的视图中,这些路径完全为空。是否有方法使其在某种程度上起作用?
    volumes:
      - "wordpress:/var/www/html"
      - "./wordpress/uploads:/var/www/html/wp-content/uploads"
      - "./wordpress/plugins:/var/www/html/wp-content/plugins"
      - "./wordpress/themes:/var/www/html/wp-content/themes"
3个回答

33

主机卷:对于一个主机卷,在您的Docker Compose文件中定义路径,如下所示:

volumes:
  - "./wordpress/uploads:/var/www/html/wp-content/uploads"

镜像中的内容不会向主机目录做任何初始化,这是设计上的考虑。


命名卷:您可以定义一个命名卷,将其映射回本地目录:

version: "2"

services:
  your-service:
    volumes:
      - uploads:/var/www/html/wp-content/uploads

volumes:
  uploads:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /path/on/host/to/wordpress/uploads

这将提供一个命名卷的初始化属性。当你的主机目录为空时,在容器创建时,Docker会将图像中 /var/www/html/wp-content/uploads 的内容复制到 /path/on/host/to/wordpress/uploads 上。


Docker 中的嵌套挂载:如果有多个嵌套的卷挂载,Docker 仍然会从图像目录中复制内容,而不是从父卷中复制。

以下是该初始化的示例。从文件系统开始:

testvol/
  data-image/
    sub-dir/
      from-image
  data-submount/
  Dockerfile
  docker-compose.yml
文件包含以下内容:
FROM busybox
COPY data-image/ /data

docker-compose.yml 文件包含:

version: "2"

services:
  test:
    build: .
    image: test-vol
    command: find /data
    volumes:
      - data:/data
      - subdir:/data/sub-dir

volumes:
  data:
  subdir:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /path/on/host/test-vol/data-submount

命名的卷已经初始化:

$ docker run -it --rm -v testvol_data:/data busybox find /data
/data
/data/sub-dir
/data/sub-dir/from-named-vol

运行测试显示复制品来自于图像from-image而不是from-named-vol

$ docker-compose -f docker-compose.bind.yml up
...
Attaching to testvol_test_1
test_1  | /data
test_1  | /data/sub-dir
test_1  | /data/sub-dir/from-image
testvol_test_1 exited with code 0

而Docker已将此内容复制到主机文件系统中:

$ ls -l data-submount/
total 0
-rw-r--r-- 1 root root 0 Jan 15 08:08 from-image
Linux中的嵌套挂载:从您的问题中可以看出,您对Linux中挂载本身的工作原理存在一些困惑。每个卷挂载在容器的挂载命名空间中运行。此命名空间为容器提供了自己的文件系统树视图。当您将一个卷挂载到该树中时,您不会修改来自父文件系统的内容,它只是覆盖了该位置上父文件系统的内容。所有更改都直接在新挂载的目录中进行,如果您卸载它,则父目录将以其原始状态可见。
因此,如果您在一个容器中挂载两个嵌套目录,例如/data/data/a,然后在第二个容器中挂载/data,则您将无法在第二个容器中看到/data/a,只有/data的内容会在那里,包括任何已经被覆盖的文件夹。

这个很好的答案在文件内部路径名称和后续引用它们的名称之间存在一些不一致(可能在输入时重命名了一些?)。例如,test-voltestvol - ᴠɪɴᴄᴇɴᴛ
此外,我不明白 docker run -it --rm -v testvol_data:/data busybox find /data 如何工作,因为 'busybox' 可能不包含 /data 目录,它只是一个带有实用程序的基础镜像。你是在 docker-compose up 之后运行这个命令而不是之前吗? - ᴠɪɴᴄᴇɴᴛ
@ᴠɪɴᴄᴇɴᴛ testvol 是组合项目名称,而 test-vol 是图像名称。这两个都不是很重要。我在可以在我的笔记本电脑上清理的东西的名称中使用 test。第二个示例有效,请在您自己的环境中运行它。卷挂载会在容器文件系统内创建目录,在 docker diff 中可以看到。 - BMitch
1
什么是解决方案? - jcarlosweb

0

我已经尝试了数小时让它运行,但我得出结论,它根本行不通。我的情况是将特定插件添加为本地开发的卷到CMS中。我在这里发布这篇文章,因为我没有在其他地方找到这种解决方法。

因此,以下内容会受到重叠卷的问题影响,导致文件夹为空。

services:
  your-service:
    volumes:
      - web-data:/var/www/html
      - ./wordpress/plugins:/var/www/html/wp-content/plugins
      - ./wordpress/themes:/var/www/html/wp-content/themes

这就是如何避免这种情况,通过将您的主题和插件绑定到另一个目录,而不是在 /var/www/html 目录中。
services:
  your-service:
    volumes:
      - web-data:/var/www/html
      - ./wordpress/plugins:/tmp/plugins
      - ./wordpress/themes:/tmp/themes

现在你必须把这些文件放到正确的位置,并且让它们与主机上的文件保持同步。

简单版本

注意:这些示例假定您的入口点是一个shell脚本。

在您的Docker入口点中:

#!/bin/bash

ln -s /tmp/plugins/my-plugin /var/www/html/wp-content/plugins/my-plugin
ln -s /tmp/themes/my-theme /var/www/html/wp-content/themes/my-theme

只要您的系统/软件解析符号链接,这应该可以正常工作。

更模块化的解决方案

我只为插件编写了这个,但您也可以以同样的方式处理主题。这将在/tmp/plugins文件夹中查找所有插件,并将它们的符号链接到/var/www/html/wp-content/plugins/<plugin>,而无需在脚本中编写硬编码的文件夹/插件名称。

#!/bin/bash

TMP_PLUGINS_DIR="/tmp/plugins"
CMS_PLUGINS_DIR="/var/www/html/wp-content/plugins"

# Loop through all paths in the /tmp/plugins folder.
for path in $TMP_PLUGINS_DIR/*/; do
  # Ignore anything that's not a directory.
  [ -d "${path}" ] || continue

  # Get the plugin name from the path.
  plugin="$(basename "${path}")"

  # Symlink the plugin to the real plugins folder.
  ln -sf $TMP_PLUGINS_DIR/$plugin CMS_PLUGINS_DIR/$plugin

  # Anything else you might need to do for each plugin, like installing/enabling it in your CMS.
done

0

我认为答案是配置绑定传播。

稍后会回报。

编辑:似乎只能在绑定挂载的卷上配置绑定传播,而且只能在 Linux 主机系统上进行。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接