Docker 匿名卷

Docker Anonymous Volumes

我在 docker-compose.yml 文件中看到 Docker 卷定义,如下所示:

-v /path/on/host/modules:/var/www/html/modules

我注意到 Drupal's official image, their docker-compose.yml file is using anonymous volumes

注意评论:

volumes:
  - /var/www/html/modules
  - /var/www/html/profiles
  - /var/www/html/themes
  # this takes advantage of the feature in Docker that a new anonymous
  # volume (which is what we're creating here) will be initialized with the
  # existing content of the image at the same location
  - /var/www/html/sites

有没有办法在容器运行之后将匿名卷与主机上的路径相关联?如果不是,匿名卷有什么意义?

完整 docker-compose.yml 示例:

version: '3.1'

services:

  drupal:
    image: drupal:8.2-apache
    ports:
      - 8080:80
    volumes:
      - /var/www/html/modules
      - /var/www/html/profiles
      - /var/www/html/themes
      # this takes advantage of the feature in Docker that a new anonymous
      # volume (which is what we're creating here) will be initialized with the
      # existing content of the image at the same location
      - /var/www/html/sites
    restart: always

  postgres:
    image: postgres:9.6
    environment:
      POSTGRES_PASSWORD: example
    restart: always

匿名卷等同于将这些目录定义为镜像 Dockerfile 中的卷。事实上,在 Dockerfile 中定义为 VOLUME 的目录是 匿名卷,如果它们没有显式映射到主机的话。

拥有它们的目的是增加灵活性。

PD: 匿名卷已经驻留在主机中 /var/lib/docker 的某处(或您配置的任何目录)。要查看它们在哪里:

docker inspect --type container -f '{{range $i, $v := .Mounts }}{{printf "%v\n" $v}}{{end}}' $CONTAINER

注意:用容器名称替换 $CONTAINER

添加更多信息以回应@JeffRSon 询问匿名卷如何增加灵活性的后续 question/comment,并回答 OP 的这个问题:

Is there a way to associate an anonymous volume with a path on the host machine after the container is running? If not, what is the point of having anonymous volumes?

TL;DR:您可以通过 'data container' 将特定的匿名卷与 运行 容器相关联,但这提供了覆盖使用的灵活性现在使用命名卷可以更好地满足这种情况。

在 Docker 1.9 中添加卷管理之前,匿名卷很有用。在此之前,您没有命名卷的选项。在 1.9 版本中,卷变成了离散的、可管理的对象,具有自己的生命周期。

在 1.9 之前,无法命名卷,您必须先创建一个数据容器来引用它

docker create -v /data --name datacontainer mysql

然后将数据容器的匿名卷挂载到需要访问该卷的容器中

docker run -d --volumes-from datacontainer --name dbinstance mysql

如今,最好使用命名卷,因为它们更易于管理且更明确。

最近匿名卷的一个可能用例是与绑定挂载结合使用。当你想绑定某个文件夹但没有任何特定的子文件夹时。然后应将这些特定的子文件夹设置为命名或匿名卷。它将保证这些子文件夹将出现在容器外部的容器文件夹中,但您根本不必将其放在主机上的绑定文件夹中。

例如,您可以将前端 NodeJS 项目构建在需要 node_modules 文件夹的容器中,但您根本不需要此文件夹进行编码。然后,您可以将项目文件夹映射到容器外的某个文件夹,并将 node_modules 文件夹设置为匿名卷。 Node_modules 文件夹将一直存在于容器中,即使您在主机上的工作文件夹中没有它。

不确定为什么 Drupal 开发人员会建议这样的设置。无论如何,我可以想到两个区别:

  1. 有了命名卷,您就有了一个表明它属于哪个项目的名称。

  2. docker-compose down && docker-compose up -d 之后,一个新的空匿名卷附加到容器。 (但旧的不会消失。docker 不会删除卷,除非你告诉它。)使用命名卷,你将获得在 docker-compose down 之前附加到容器的卷。

因此,您可能不想将不想丢失的数据放入匿名卷(如 db 或其他)。同样,它们不会自行消失。但是在 docker-compose down && docker-compose up -d && docker volume prune 之后,命名卷将继续存在。

对于不太重要的事情(比如 node_modules),我没有强烈的支持或反对命名卷的论据。

Is there a way to associate an anonymous volume with a path on the host machine after the container is running?

为此您需要更改设置,例如/var/www/html/modules -> ./modules:/var/www/html/modules,然后执行 docker-compose up -d。但这会将匿名卷变成绑定安装。您需要将数据从卷复制到 ./modules。同样,您可以将匿名卷变成命名卷。