Usage: bindit¶
Bindit is a command-line application. The basic usage is to prepend bindit
to the
container runner command you would ordinarily use.
Motivating example¶
Let’s say you wanted to use a docker container to list the contents of your current home directory you might do something like this on a unix-based system (Linux, OS X):
$ docker run -v "$HOME":/data alpine:latest ls /data
With bindit, the bind mount is created automatically by detecting the file path reference in the container image arguments. You can basically pretend that the container has access to your host file system. So this works:
$ bindit docker run alpine:latest ls "$HOME"/data
Bindit mounts are mapped to a new /bindit
path inside the container to avoid
clobbering directories that might be necessary for the container to run (in particular,
messing with the container home directory as singularity does by default often breaks
containers). If we set the --dryrun
flag the docker command prints to standard out
instead of running, and we can see the mapping bindit created:
$ bindit --dryrun docker run alpine:latest ls "$HOME"
docker run -v /Users/jc01:/bindit/Users/jc01 alpine:latest ls /bindit/Users/jc01
Turning the above examples into a re-usable application that can be added to your path is easy - see Usage: bindit_partial.
Default and optional behavior¶
Bindit’s default behavior can be controlled with the following flags:
-a, –absonly¶
Only auto-bind absolute paths. Useful if you call bindit from a folder that has
sub-folders which shadow binaries inside the container (python
is a frequent offender
for me).
-d, –dryrun¶
Return a formatted shell command without invoking container runner. Useful for debugging, and when you want to defer running the container to a different context (for instance, HPC job submission).
Note that bindit does require the container runner on path to parse container runner arguments correctly, so for instance, it’s not good practice to dryrun docker jobs on a machine that does not have docker available (or indeed a different docker version from what you use in production).
-i, –ignorepath¶
bindit won’t attempt to bind any path that is a sub-directory of the specified path(s).
You can use this flag multiple times. The result is appended to a list of default unix
root folders (see bindit.IGNORE_PATH
).
-l, –loglevel¶
Set the verbosity of log messages printed to the shell standard out. Default level is INFO, try DEBUG for more detail.
Combining user-defined and automatic binds¶
We have seen that bindit defaults to creating new bind mounts in the /bindit
directory inside the container. But bindit also detects user-specified binds, and will
use them whenever possible (for instance, when the user-specified bind is a parent of
the input path):
$ mkdir -p foo/bar
$ bindit --dryrun docker run -v $(PWD):/container alpine:latest ls foo
docker run -v /Users/jc01/temp:/container alpine:latest ls /container/foo
Limitations¶
There are limitations to what paths bindit can detect automatically. The workaround for these is typically to use absolute paths or to specify manual binds.
Specifying output paths¶
Bindit can only detect relative paths when they exist. Absolute paths work either way. This can trip you up when calling a container application with an argument that defines the output file path. These must always be absolute (unless it’s a folder, or you are otherwise modifying or overwriting an existing path).
This can lead to seemingly baffling behavior. For example, suppose we want to use
ImageMagick to downsize an image and save it to a new name. We use --dryrun
to
preview what the final docker run command will look like. Note that the input image has
been re-mapped correctly, but the output image hasn’t because it doesn’t exist yet:
$ touch in.jpg
$ rm -f out.jpg
$ bindit --dryrun docker run dpokidov/imagemagick in.jpg -resize 100x100 out.jpg
docker run -v /Users/jc01/temp:/bindit/Users/jc01/temp dpokidov/imagemagick \
/bindit/Users/jc01/temp/in.jpg -resize 100x100 out.jpg
If we instead specify an absolute output path, both in.jpg and out.jpg get re-mapped to the correct locations:
$ bindit --dryrun docker run dpokidov/imagemagick in.jpg -resize 100x100 "$PWD"/out.jpg
docker run -v /Users/jc01/temp:/bindit/Users/jc01/temp dpokidov/imagemagick \
/bindit/Users/jc01/temp/in.jpg -resize 100x100 /bindit/Users/jc01/temp/out.jpg
Handling implicit output paths¶
Bindit can only recognize paths that are explicitly provided when the container runner
is called. If you are using bindit to wrap an application that generates new files
without any API control over where they go (for instance by writing to cwd as in the
default gzip -d
behavior), this won’t work because bindit won’t be able to
anticipate this output.