Search code examples
dockerexternalvolumesenv-file

Multiple binds mounts from external config


I am putting together some tools that need access to config spread across different locations on host machines.

For reasons beyond my control, different hosts have different mappings, so I need the bind mounts to vary.

Is is possible to externalize mount configurations so we can dynamically generate this per host?

I have seen docker-compose examples that use JSON, but can't find any docker run equivalent (docker-compose isn't an option for my use-case).

I have tried the following :

container-env.json:

    {
      "mounts" : [
        "type=bind,source=//c/Users/foo/.ssh,target=/root/.ssh,ro",
        "type=bind,source=//c/Users/foo/Projects/ops-tools,target=/root/ops-tools",
        "type=bind,source=//c/tmp/certs,target=/root/certs"
      ]
    }

docker run --env-file container-env.json...

however docker complains with error 'poorly formatted environment: variable '"mounts" : [' contains whitespaces.', removing whitespace suppresses the error but nothing is mounted


Solution

  • You can't use --env-file for that - that's only for environment variables.

    I don't know of a way to do this with Docker natively, but you can hack something together using Bash and jq. Here's a command which turns your JSON file into a series of mount options:

    < container-env.json jq -r '.mounts | map("--mount \"" + . + "\"") | join("\n")'
    

    That produces this output:

    --mount "type=bind,source=//c/Users/foo/.ssh,target=/root/.ssh,ro"
    --mount "type=bind,source=//c/Users/foo/Projects/ops-tools,target=/root/ops-tools"
    --mount "type=bind,source=//c/tmp/certs,target=/root/certs"
    

    Here's how you'd use it in a script.

    #!/usr/bin/env bash
    mount_options="$(< container-env.json jq -r '.mounts | map("--mount \"" + . + "\"") | join("\n")')"
    docker run $mount_options <rest of command goes here>