【问题标题】:Docker Compose - Share named volume between multiple containersDocker Compose - 在多个容器之间共享命名卷
【发布时间】:2017-11-01 05:47:56
【问题描述】:

我正在使用 docker-compose 和 v3。我正在尝试在 docker 中挂载一个卷:

./appdata:/appdata

我想将此作为一个卷,然后从多个容器中引用该卷。 volume configuration reference 仅将data-volume: 显示为命名卷,没有任何值,因此看起来不像上面那样。

services:

    nginx:
        build: ./nginx/
        ports:
            - 80:80
        links:
            - php
        volumes:
            - app-volume

    php:
        build: ./php/
        expose:
            - 9000
        volumes:
            - app-volume

volumes:
     app-volume: ./appdata:/appdata

这给了我:

错误:在文件 './docker-compose.yml' 中,卷 'app-volume' 必须是映射而不是字符串。

显然我知道我需要更改 volumes 键/值对,但我不确定如何更改它以便我可以在服务之间共享卷。

我还检查了volumes_from,但这实际上只允许从其他容器继承。我见过有人在另一个包含他们想要的映射的容器上使用volumes_from,但设置了command: true,这样容器就永远不会真正运行,这对我来说就像是一个hack。

我该怎么做?


注意,我确实有以下工作:

nginx:
    volumes:
        - ./appdata:/appdata
php:
    volumes:
        - ./appdata:/appdata

但这只是重复,我希望命名卷可以帮助我避免:-)

【问题讨论】:

标签: docker docker-compose


【解决方案1】:

命名卷可以通过以下方式跨容器共享:

services:
    nginx:
        build: ./nginx/
        ports:
            - 80:80
        links:
            - php
        volumes:
            - app-volume:location_in_the_container

    php:
        build: ./php/
        expose:
            - 9000
        volumes:
            - app-volume:location_in_the_container

volumes:
     app-volume: 

这是我用来更好理解的示例配置。我将从我的web 容器生成的静态文件暴露给名为static-content 的命名卷,然后由nginx 容器读取和提供服务:

services:
  nginx:
    container_name: nginx
    build: ./nginx/

    volumes:
      - static-content:/usr/src/app

  web:
    container_name: web
    env_file: .env
    volumes:
      - static-content:/usr/src/app/public
    environment:
      - NODE_ENV=production

    command: npm run package

volumes:
  static-content:

【讨论】:

  • static_content 在主机文件系统上的位置设置在哪里?
  • app-volume: location_in_the_container 中的空格是错误的。
  • 如果nginx 容器中的/usr/src/app 和web 容器中的/usr/src/app/public 都获得了原始内容,会使用哪一个,为什么?
  • @TravisBear 对于这个用例(在容器之间共享数据),实际上不需要在主机上安装它。静态数据的示例很棒 - 您在一个容器中执行 collectstatic 并希望结果在另一个容器中可用,但您不关心主机文件夹
  • @Kannaj TravisBear 的问题是正确识别我认为最令人困惑的问题的问题。如何在撰写文件中指定命名卷的来源?我不想让 docker 引擎来决定在主机上存储命名卷的位置,我想指定一个路径。
【解决方案2】:

这在不使用命名卷的情况下解决了这个问题:

      volumes:
          - ./appdata:/appdata

所以,它看起来像:

services:

  nginx:
      build: ./nginx/
      ports:
          - 80:80
      links:
          - php
      volumes:
          - ./appdata:/appdata

  php:
      build: ./php/
      expose:
          - 9000
      volumes:
          - ./appdata:/appdata

【讨论】:

  • 啊,好时机!我在上面做了这个(见我的改变)。但是,我们似乎仍在复制映射。如果我使用超过 3 个容器,它会变大。我们可以使用命名容器来避免这种重复吗?
  • 问题是命名卷不仅仅是语法和清晰的代码。它将在 docker 数据安装目录中创建一个卷,并且您不会在那里拥有本地文件(./appdata)。对你有用吗?
  • 我绝对需要./appdata,这就是我想要做的。不过,请在此处留下这个答案:) +1
  • 如果我有两个相同图像的容器,在一个容器中上传文件(通过上传文件服务),它会在另一个容器中可用?如果没有,我该怎么做?
【解决方案3】:

从 docker-compose 3 版本开始删除了名为 volumes 的 docker。

但是,您可以使用extension-fields 来避免重复卷源并防止自己将来出现拼写错误:

version: '3.5'

x-services-volume:
  &services-volume
  type: bind
  source: ./appdata
  target: /appdata

services:

    nginx:
        build: ./nginx/
        ports:
            - 80:80
        links:
            - php
        volumes: *services-volume

    php:
        build: ./php/
        expose:
            - 9000
        # Use same way as for nginx if target override not needed.
        volumes:
            - <<: *services-volume
            target: /opt/target-override

注意:该功能从 3.4 版文件格式开始可用。

【讨论】:

  • 如果 *services-volume 只是一个指向上面设置的值的指针,这看起来很棒......我必须尝试一下。
  • @Jimbo 是的,是的,还要注意docker-compose文件版本应该是3.4+
  • 命名卷,也就是顶级 volumes 字段,似乎仍然是 v3 of docker-compose 中的东西。
  • @and0r 文件夹是共享的,想象一下谷歌驱动器和真实用户 + 共享文件夹,如果有人删除该文件夹上的文件,那么其他用户就没有了
  • @AndriyIvaneyko 实际删除了命名卷吗?找不到任何相关参考。
【解决方案4】:

以前的答案对我有很大帮助(谢谢!),但花了一些时间才弄清楚如何设置选项以创建共享的tmpfs 卷(内存文件系统)。我分享它是为了让处于相同情况的开发人员的生活更轻松。

仅显示docker-compose.yml 相关部分的示例:

version: '3'

volumes:
  shared-tmpfs:
    driver: local
    driver_opts:
      type: "tmpfs"
      device: "tmpfs"
      o: "size=256m,uid=1000"

services:
  nginx:
    volumes:
      - shared-tmpfs:/tmp/mytmpfs

  php-fpm:
    volumes:
      - shared-tmpfs:/tmp/mytmpfs

我用它来让我的 SSD 在开发/监视模式下免于大量写入(构建大量静态 html 文件)。

您可以在官方 Docker 文档 here 中阅读有关 driver_opts 的更多信息。

【讨论】:

  • 接受的答案对您不起作用怎么办?在这里您必须定义它两次 - 使用接受的答案的 &amp; 和 * 表示法,所以您只需定义一次?
  • @Jimbo 我确实喜欢接受的答案,但我无法用这种方法达到同样的效果。该解决方案绑定现有目录,我的解决方案使用给定选项即时创建一个新的tmpfs 卷。这可能是我的错,但我无法将其转换为接受答案的形式(扩展字段)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-28
  • 2017-01-31
  • 2021-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多