我在
docker-compose.yml
文件中看到了 Docker 卷定义,如下所示:
-v /path/on/host/modules:/var/www/html/modules
我注意到 Drupal 的官方镜像,他们的
docker-compose.yml
文件正在使用 匿名卷。
注意评论:
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
添加更多信息以回应 @JeffRSon 的后续问题/评论,询问匿名卷如何增加灵活性,并回答 OP 的这个问题:
有没有办法在容器运行后将匿名卷与主机上的路径关联起来?如果不是,那么拥有匿名卷有什么意义?
TL;DR:您可以通过“数据容器”将特定的匿名卷与正在运行的容器相关联,但这提供了灵活性来覆盖现在通过使用命名卷可以更好地服务的用例。
在 Docker 1.9 中添加卷管理之前,匿名卷很有用。在此之前,您无法选择命名卷。在 1.9 版本中,卷成为具有自己生命周期的离散、可管理的对象。
在 1.9 之前,无法命名卷,您必须首先创建数据容器来引用它
docker create -v /data --name datacontainer mysql
然后将数据容器的匿名卷挂载到需要访问该卷的容器中
docker run -d --volumes-from datacontainer --name dbinstance mysql
如今,最好使用命名卷,因为它们更容易管理且更明确。
匿名卷相当于将这些目录定义为镜像 Dockerfile 中的 VOLUME。事实上,如果没有明确映射到主机,则在 Dockerfile 中定义为 VOLUME 的目录是匿名卷。
拥有它们的目的是增加灵活性。
PD: 匿名卷已驻留在主机中的 /var/lib/docker (或您配置的任何目录)中的某个位置。查看他们在哪里:
docker inspect --type container -f '{{range $i, $v := .Mounts }}{{printf "%v\n" $v}}{{end}}' $CONTAINER
注意:用容器名称替换
$CONTAINER
。
如今,匿名卷的一个可能的用例是与绑定挂载结合使用。当您想要绑定某个文件夹但没有任何特定子文件夹时。然后应将这些特定子文件夹设置为命名或匿名卷。它将保证这些子文件夹将出现在您的容器文件夹中,该文件夹位于容器之外,但您根本不必将其放在主机上的绑定文件夹中。
例如,您可以将前端 NodeJS 项目构建在容器中,其中需要 node_modules 文件夹,但您根本不需要此文件夹来进行编码。然后,您可以将项目文件夹映射到容器外部的某个文件夹,并将 node_modules 文件夹设置为匿名卷。 Node_modules 文件夹将始终存在于容器中,即使您的工作文件夹中的主机上没有它。
不知道为什么 Drupal 开发人员建议这样的设置。无论如何,我能想到两个区别:
使用命名卷,您可以通过名称来表明它属于哪个项目。
在
docker-compose down && docker-compose up -d
之后,一个新的空匿名卷将附加到容器。 (但是旧的卷不会消失。docker
不会删除卷,除非您告诉它。)使用命名卷,您将获得之前附加到容器的卷 docker-compose down
。
因此,您可能不想将不想丢失的数据放入匿名卷(例如数据库或其他东西)中。再说一遍,它们不会自行消失。但在
docker-compose down && docker-compose up -d && docker volume prune
之后,一个命名的卷将继续存在。
对于不太重要的事情(例如
node_modules
),我没有强有力的论据支持或反对命名卷。
有没有办法在容器运行后将匿名卷与主机上的路径关联起来?
为此,您需要更改设置,例如
/var/www/html/modules
-> ./modules:/var/www/html/modules
,然后执行 docker-compose up -d
。但这会将匿名卷变成绑定安装。您需要将数据从卷复制到 ./modules
。同样,您可以将匿名卷变成命名卷。
我使用匿名卷来不反映主机和容器之间的
node_modules
。 node_modules
由 pnpm 管理,因此不能同时在 Windows(此处作为主机)和 linx(此处作为容器)上工作。因此,它对我来说非常方便(可能对 docker 引擎也是如此;))自动在两个方向上反映代码并隔离 node_modules
。
这是我的
docker-compose.yml
version: '3.8'
services:
container:
build: .
volumes:
# Here the changes will be reflected in both directions
- .:/app
# Making an anonymous volume for node_modules
# so that we can overwrite it in the container
# and the changes will never be reflected
# on the host
- /app/node_modules
working_dir: /app