Search code examples
dockerdocker-composeprestodocker-volumetrino

docker compose volume to existing directory hides existing files in the same parent dir


While using docker compose with the prestosql image I ran into a particular problem.

If I configure compose to mount a volume to an existing directory in the image, when the container starts, all files that exist in the same lever as the mount point disappear. All other files in the parent directory disappear, only the mountpoint remains (with the proper volume content inside)

My docker-compose.yml is as follows:

version: '2.2'
services:
  prestosql:
    image: prestosql/presto:329
    volumes:
       - ./src/test/resources/presto/catalog/:/usr/lib/presto/etc/catalog/

If I exec a bash into the prestosql container and ls the /usr/lib/presto/etc/ I get:

[presto@7df706ccb1bc presto]$ ls -lah /usr/lib/presto/etc/
total 8.0K
drwxr-xr-x 3 root   root   4.0K Jan 30 15:12 .
drwxr-xr-x 1 presto presto 4.0K Jan 30 15:12 ..
drwxr-xr-x 4 presto presto  128 Jan 25 18:09 catalog

However, if I repeat the procedure without the volume configuration and ls the /usr/lib/presto/etc/ I get:

[presto@7b2c2178f6e9 /]$ ls -lah /usr/lib/presto/etc/
total 28K
drwxr-xr-x 3 presto presto 4.0K Jan 23 12:22 .
drwxr-xr-x 3 presto presto 4.0K Jan 23 12:22 ..
drwxr-xr-x 2 presto presto 4.0K Jan 23 12:22 catalog
-rw-r--r-- 1 presto presto  178 Jan 23 12:22 config.properties
-rw-r--r-- 1 presto presto  295 Jan 23 12:22 jvm.config
-rw-r--r-- 1 presto presto   57 Jan 23 12:22 log.properties
-rw-r--r-- 1 presto presto   85 Jan 23 12:22 node.properties

Running an inspect on the container show only the volume on mounts:

❯ docker inspect -f '{{ .Mounts }}' 7df706ccb1bc
[{bind  /blablabla/src/test/resources/presto/catalog /usr/lib/presto/etc/catalog  rw true rprivate}]

Is this expected behaviour?


Solution

  • It seems like the presto image does not itself contain the /usr/lib/presto/etc/ directory, but when the container start the entrypoint (run-presto) creates a symlink from /usr/lib/presto/default/etc to /usr/lib/presto/etc this way:

    if [[ ! -d /usr/lib/presto/etc ]]; then
      if [[ -d /etc/presto ]]; then
        ln -s /etc/presto /usr/lib/presto/etc
      else
        ln -s /usr/lib/presto/default/etc /usr/lib/presto/etc
      fi 
    fi
    

    So basically if you mount your file anywhere under /usr/lib/presto/etc this link would not be created so you'd end up having a single file under that directory hierarchy.

    The solution is pretty simple, just mount the file under /usr/lib/presto/default/etc instead:

    ...
    volumes:
       - ./src/test/resources/presto/catalog/:/usr/lib/presto/default/etc/catalog/
    

    Just as some additional note: Based on their documentation:

    Configuration is expected to be mounted to either to /etc/presto or /usr/lib/presto/etc (the latter takes precedence). If neither of these exists then the default single node configuration will be used.

    It seems like they expect that the whole configuration (i.e. everything under etc) should be mounted as a whole to /etc/presto or /usr/lib/presto/etc, so they do not expect a single file to be added/replaced that's why your approach did not work the way you wanted.