Docker Compose - 在多个容器之间共享命名卷

Posted

技术标签:

【中文标题】Docker Compose - 在多个容器之间共享命名卷【英文标题】:Docker Compose - Share named volume between multiple containers 【发布时间】: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

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

【问题讨论】:

你可以在这个答案中找到答案:***.com/a/49920624 【参考方案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/appweb 容器中的/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 卷。这可能是我的错,但我无法将其转换为接受答案的形式(扩展字段)。

以上是关于Docker Compose - 在多个容器之间共享命名卷的主要内容,如果未能解决你的问题,请参考以下文章

Docker Compose介绍

docker-compose 安装

Docker Compose

docker compose 服务启动顺序控制

无法使用nginx-proxy和dnsmasq在带有docker-compose的容器之间访问虚拟主机

单机编排之-Docker Compose