【问题标题】:Mixing named volumes and bind mounting in Docker?在 Docker 中混合命名卷和绑定挂载?
【发布时间】:2018-01-15 10:08:15
【问题描述】:

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

【问题讨论】:

    标签: docker docker-compose docker-stack


    【解决方案1】:

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

    因此,如果您在一个容器中挂载两个嵌套目录,例如/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 中看到它。
    • 解决办法是什么?
    【解决方案2】:

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

    将报告。

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

    【讨论】:

      【解决方案3】:

      我已经尝试让它工作了几个小时,但我得出的结论是它不会。我的案例是将特定插件添加到 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-07-05
        • 2020-07-26
        • 2017-01-26
        • 1970-01-01
        • 2019-08-23
        • 2019-01-09
        • 1970-01-01
        • 2021-11-28
        相关资源
        最近更新 更多