Wednesday, 14 October 2020

Tinkering with Docker and relative vs. absolute paths for volume mounting

 A colleague asked how he might use a relative path e.g. ~/foobar or ../foobar instead of an absolute path e.g. /home/Dave or /tmp/foobar when mapping a path on the host to a path inside a container, using Docker for Mac.

Well, I had a play ....

For reference, Docker uses a concept known as bind mounting as evidenced by docker run --help 

  -v, --volume list                    Bind mount a volume

to make a file-system on the host available inside a running container.

I used BusyBox ( busybox ) : -

docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
busybox             latest              6858809bf669        5 weeks ago         1.23MB

and tinkered with various options.

Scenario 1 - using a shortcut for /home/<user> specifically ~

echo "Hello World!" > ~/foo.txt

docker run --rm -it --volume ~:/tmp busybox:latest sh

and then validate from inside the container: -

cat /tmp/foo.txt

Hello World!

exit

so that works ....

Scenario 2 - using a shortcut / relative path such as ..

mkdir -p ~/foobar/snafu

echo "Hello World!" > ~/foobar/greeting.txt

docker run --rm -it --volume "..":/tmp busybox:latest sh

docker: Error response from daemon: create ..: ".." includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.
See 'docker run --help'.

Erk, not so good .....

Whilst I can do this: -

docker run --rm -it --volume ~/foobar:/tmp busybox:latest sh

cat /tmp/greeting.txt 

Hello World!

that kinda defeats the object ....

Enter .... realpath

which realpath

/usr/local/bin/realpath

realpath --version

realpath (GNU coreutils) 8.32
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Padraig Brady.

realpath --help

Usage: realpath [OPTION]... FILE...
Print the resolved absolute file name;
all but the last component must exist

  -e, --canonicalize-existing  all components of the path must exist
  -m, --canonicalize-missing   no path components need exist or be a directory
  -L, --logical                resolve '..' components before symlinks
  -P, --physical               resolve symlinks as encountered (default)
  -q, --quiet                  suppress most error messages
      --relative-to=DIR        print the resolved path relative to DIR
      --relative-base=DIR      print absolute paths unless paths below DIR
  -s, --strip, --no-symlinks   don't expand symlinks
  -z, --zero                   end each output line with NUL, not newline

      --help     display this help and exit
      --version  output version information and exit

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation <https://www.gnu.org/software/coreutils/realpath>
or available locally via: info '(coreutils) realpath invocation'

I'd heard about realpath from the colleague who'd asked the question in the first place ... so I installed it ....

brew install realpath

and so back to Docker ....

docker run --rm -it --volume `realpath ..`:/tmp busybox:latest sh

cat /tmp/greeting.txt 

Hello World

which works a treat - the trick is to use the shell-within-a-shell trick of enclosing one command inside another, via the double backpack ( ` ) symbol.

So I'm asking realpath where am I ....

realpath ..

/Users/hayd/foobar

and then using the results of that as the from for the Docker bind mount.

Scenario 3 - absolute paths that are absolutely horrible

So even though this wasn't something for which my colleague asked, I wanted to see what happened with horrible paths that include space characters .....

Personally I *HATE* spaces in paths - Microsoft did it with Windows a few decades back, with C:\Program Files\ etc. and that used to play havoc with Java and class paths.

Here's one that IBM Notes uses, for dumps etc.

cd ~/Library/Application\ Support/IBM\ Notes\ Data/IBM_TECHNICAL_SUPPORT/

Within that path, there's a subdirectory: -

SmartUpgrade

This entire path expands out to: -

/Users/hayd/Library/Application Support/IBM Notes Data/IBM_TECHNICAL_SUPPORT/SmartUpgrade

so we test it thusly: -

cd "/Users/hayd/Library/Application Support/IBM Notes Data/IBM_TECHNICAL_SUPPORT/SmartUpgrade

echo "Hello World!" > ./greeting.txt

docker run --rm -it --volume "/Users/hayd/Library/Application Support/IBM Notes Data/IBM_TECHNICAL_SUPPORT/SmartUpgrade":/tmp busybox:latest  sh

cat /tmp/greeting.txt 

Hello World!

Interestingly, the realpath "hack" didn't work: -

docker run --rm -it --volume `realpath .`:/tmp busybox:latest sh

docker: invalid reference format: repository name must be lowercase.
See 'docker run --help'.

docker run --rm -it --volume "`realpath .`":/tmp busybox:latest sh

cat /tmp/greeting.txt

Hello World!

So now we are wrapping the output of `realpath .` in double-quotes ... otherwise, the output of realpath throws back space characters to the upper shell, which breaks docker run .....

What fun!

No comments:

Yay, VMware Fusion and macOS Big Sur - no longer "NAT good friends" - forgive the double negative and the terrible pun ...

After macOS 11 Big Sur was released in 2020, VMware updated their Fusion product to v12 and, sadly, managed to break Network Address Trans...