docker-compose 安装的卷是空的,但在 Docker 映像构建期间创建的其他卷被填充

docker-compose mounted volume is empty, but other volumes created during Docker image build are populated

从一个空目录开始,我创建了这个 docker-compose.yml:

version: '3.9'
services:
  neo4j:
    image: neo4j:3.2
    restart: unless-stopped
    ports:
      - 7474:7474
      - 7687:7687
    volumes:
      - ./conf:/conf
      - ./data:/data
      - ./import:/import
      - ./logs:/logs
      - ./plugins:/plugins
    environment:
      # Raise memory limits
      - NEO4J_dbms_memory_pagecache_size=1G
      - NEO4J_dbms.memory.heap.initial_size=1G
      - NEO4J_dbms_memory_heap_max__size=1G

然后我添加 import 目录,其中包含我打算在容器中使用的数据文件。

此时,我的目录如下所示:

0 drwxr-xr-x   9 cc  staff  288 Dec 11 18:57 .
0 drwxr-xr-x   5 cc  staff  160 Dec 11 18:15 ..
8 -rw-r--r--   1 cc  staff  458 Dec 11 18:45 docker-compose.yml
0 drwxr-xr-x  20 cc  staff  640 Dec 11 18:57 import

I 运行 docker-compose up -d --build,容器构建完成。现在本地目录如下所示:

0 drwxr-xr-x   9 cc  staff  288 Dec 11 18:57 .
0 drwxr-xr-x   5 cc  staff  160 Dec 11 18:15 ..
0 drwxr-xr-x   2 cc  staff   64 Dec 11 13:59 conf
0 drwxrwxrwx@  4 cc  staff  128 Dec 11 18:08 data
8 -rw-r--r--   1 cc  staff  458 Dec 11 18:45 docker-compose.yml
0 drwxr-xr-x  20 cc  staff  640 Dec 11 18:57 import
0 drwxrwxrwx@  3 cc  staff   96 Dec 11 13:59 logs
0 drwxr-xr-x   3 cc  staff   96 Dec 11 15:32 plugins

已创建 confdatalogsplugins 目录。

datalogs 是从 Neo4j 图像的构建中填充的,并且 confplugins 是空的,正如预期的那样。

我用docker exec查看容器上的目录结构:

     8 drwx------    1 neo4j    neo4j         4096 Dec 11 23:46 .
     8 drwxr-xr-x    1 root     root          4096 May 11  2019 ..
    36 -rwxrwxrwx    1 neo4j    neo4j        36005 Feb 18  2019 LICENSE.txt
   128 -rwxrwxrwx    1 neo4j    neo4j       130044 Feb 18  2019 LICENSES.txt
    12 -rwxrwxrwx    1 neo4j    neo4j         8493 Feb 18  2019 NOTICE.txt
     4 -rwxrwxrwx    1 neo4j    neo4j         1594 Feb 18  2019 README.txt
     4 -rwxrwxrwx    1 neo4j    neo4j           96 Feb 18  2019 UPGRADE.txt
     8 drwx------    1 neo4j    neo4j         4096 May 11  2019 bin
     4 drwxr-xr-x    2 neo4j    neo4j         4096 Dec 11 23:46 certificates
     8 drwx------    1 neo4j    neo4j         4096 Dec 11 23:46 conf
     0 lrwxrwxrwx    1 root     root             5 May 11  2019 data -> /data
     4 drwx------    1 neo4j    neo4j         4096 Feb 18  2019 import
     8 drwx------    1 neo4j    neo4j         4096 May 11  2019 lib
     0 lrwxrwxrwx    1 root     root             5 May 11  2019 logs -> /logs
     4 drwx------    1 neo4j    neo4j         4096 Feb 18  2019 plugins
     4 drwx------    1 neo4j    neo4j         4096 Feb 18  2019 run

我的问题是容器中的import目录是空的。 datalogs 目录不是空的。

我本地的 datalogs 目录具有 confplugins 没有的扩展属性:

xattr -l data
com.docker.grpcfuse.ownership: {"UID":100,"GID":101}

我能识别的唯一区别是那些目录包含 docker-compose 在抓取 Neo4j 图像时创建的数据。

有谁知道这里发生了什么,并告诉我如何让它工作?我正在使用 Mac OS X 10.15 和 docker-compose 版本 1.27.4,构建 40524192.

谢谢。

TL;DR:您当前的设置可能工作正常。


了解您观察到的具体行为:

  1. 在容器启动时,Docker 将在主机上创建空目录(如果它们不存在),并在容器内创建挂载点目录。 (这就是出现这些目录的原因。)

  2. Docker 从不 将图像中的数据复制到绑定装载中。此行为仅发生在命名卷上(并且仅在您第一次使用它们时发生,不会在以后运行时发生;并且仅在本机 Docker 上发生,而不会在 Kubernetes 上发生)。

  3. 但是,标准数据库图像通常知道如何初始化一个空数据目录。在 neo4j image, its Dockerfile ends with an ENTRYPOINT directive that runs at container startup; that docker-entrypoint.sh 的情况下,知道如何进行各种首次设置。这就是数据进入 ./data.

    的方式
  4. 图像还声明了一个 WORKDIR /var/lib/neo4j(通过中间环境变量)。这就解释了,在您的 ls -l 列表中,为什么会有像 data -> /data 这样的符号链接。您的绑定挂载是 /import,但如果您 docker-compose exec neo4j ls import,它将看起来相对于 WORKDIR,这就是为什么目录看起来是空的。

  5. 但是,entrypoint脚本专门在容器内部寻找/import目录,如果存在且可读,则设置环境变量NEO4J_dbms_directories_import=/import.

这一切都向我表明您的设置是正确的,如果您尝试执行导入,它将正常工作并看到您的主机数据。您正在查看映像中的 /var/lib/neo4j/import 目录,它是空的,但映像启动知道还要在容器中查找 /import,并且您的挂载点在那里。