16

混合命名卷绑定挂载如何工作?使用以下设置,绑定挂载的路径在绑定挂载中是否仍然可用,因为它们存在于绑定挂载中? /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"
4

3 回答 3

19

主机卷:对于主机卷,使用 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

Dockerfile 包含:

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 中的工作方式似乎有些混乱。每个卷挂载都在容器的挂载命名空间中运行。这个命名空间为容器提供了自己的文件系统树视图。当您将卷挂载到该树中时,您不会修改父文件系统中的内容,它只是覆盖了该位置的父文件系统的内容。所有更改都直接发生在新挂载的目录中,如果您要卸载它,则父目录将以其原始状态可见。

因此,如果您在一个容器中挂载两个嵌套目录,例如/dataand /data/a,然后/data在第二个容器中挂载,您将不会/data/a从第二个容器中的第一个容器中看到,只有 的内容/data会在那里,包括任何已挂载的文件夹在上面。

于 2018-01-15T13:53:47.537 回答
0

我相信答案是配置绑定传播。

将报告回来。

编辑:似乎您只能在绑定挂载的卷上配置绑定传播,并且只能在 linux 主机系统上配置。

于 2018-01-15T10:22:11.870 回答
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
于 2021-08-04T08:23:30.530 回答