public static String resolveRelativeVolumeBinding(File baseDir, String bindingString) {

        // a 'services:' -> service -> 'volumes:' may be formatted as:
        // (https://docs.docker.com/compose/compose-file/compose-file-v2/#volumes-volume_driver)
        //
        // volumes:
        //  # Just specify a path and let the Engine create a volume
        //  - /var/lib/mysql
        //
        //  # Specify an absolute path mapping
        //  - /opt/data:/var/lib/mysql
        //
        //  # Path on the host, relative to the Compose file
        //  - ./cache:/tmp/cache
        //
        //  # User-relative path
        //  - ~/configs:/etc/configs/:ro
        //
        //  # Named volume
        // - datavolume:/var/lib/mysql

        String[] pathParts = bindingString.split(":");
        if (SystemUtils.IS_OS_WINDOWS &&  WINDOWS_DRIVE_PATTERN.matcher(bindingString).matches() && pathParts.length>2) {
            String[] winPathParts = new String[pathParts.length-1];
            winPathParts[0]=pathParts[0]+":"+pathParts[1];
            for (int i=1;i<winPathParts.length;i++) {
                winPathParts[i]=pathParts[i+1];
            }
            pathParts=winPathParts;
        }
        String localPath = pathParts[0];

        if (isRelativePath(localPath)) {
            File resolvedFile;
            if (isUserHomeRelativePath(localPath)) {
                resolvedFile = resolveAbsolutely(prepareUserHomeRelativePath(localPath), getUserHome());
            } else {
                if (!baseDir.isAbsolute()) {
                    throw new IllegalArgumentException("Base directory '" + baseDir + "' must be absolute.");
                }
                resolvedFile = resolveAbsolutely(localPath, baseDir.getAbsolutePath());
            }
            try {
                localPath = resolvedFile.getCanonicalFile().getAbsolutePath();
            } catch (IOException e) {
                throw new RuntimeException("Unable to canonicalize '" + resolvedFile + "'");
            }
        } else if (SystemUtils.IS_OS_WINDOWS && (localPath.contains(DOUBLE_DOT))) {
            File resolvedFile=new File(localPath);
            try {
                localPath = resolvedFile.getCanonicalFile().getAbsolutePath();
            } catch (IOException e) {
                throw new RuntimeException("Unable to canonicalize '" + resolvedFile + "'");
            }
        }

        if (pathParts.length > 1) {
            pathParts[0] = localPath;
            return join(":", pathParts);
        }

        return localPath;
    }
Resolves relative paths in the supplied {@code bindingString}, and returns a binding string that has relative
paths replaced with absolute paths.  If the supplied {@code bindingString} does not contain a relative path, it
is returned unmodified.
<h3>Discussion:</h3>
<p>
Volumes may be defined inside of {@code service} blocks <a href="https://docs.docker.com/compose/compose-file/compose-file-v2/#volumes-volume_driver">
as documented here</a>:
</p>
<pre>
volumes:
# Just specify a path and let the Engine create a volume
- /var/lib/mysql

# Specify an absolute path mapping
- /opt/data:/var/lib/mysql

# Path on the host, relative to the Compose file
- ./cache:/tmp/cache

# User-relative path
- ~/configs:/etc/configs/:ro

# Named volume
- datavolume:/var/lib/mysql"
</pre>
<p>
This method only operates on volume strings that are relative: beginning with {@code ./}, {@code ../}, or
{@code ~}.  Relative paths beginning with {@code ./} or {@code ../} are absolutized relative to the supplied
{@code baseDir}, which <em>must</em> be absolute.  Paths beginning with {@code ~} are interpreted relative to
{@code new File(System.getProperty("user.home"))}, and {@code baseDir} is ignored.
</p>
<p>
Volume strings that do not begin with a {@code ./}, {@code ../}, or {@code ~} are returned as-is.
</p>
<h3>Examples:</h3>
<p>
Given {@code baseDir} equal to "/path/to/basedir" and a {@code bindingString} string equal to
"./reldir:/some/other/dir", this method returns {@code /path/to/basedir/reldir:/some/other/dir}
</p>
<p>
Given {@code baseDir} equal to "/path/to/basedir" and a {@code bindingString} string equal to
"../reldir:/some/other/dir", this method returns {@code /path/to/reldir:/some/other/dir}
</p>
<p>
Given {@code baseDir} equal to "/path/to/basedir" and a {@code bindingString} string equal to
"~/reldir:/some/other/dir", this method returns {@code /home/user/reldir:/some/other/dir}
</p>
<p>
Given {@code baseDir} equal to "/path/to/basedir" and a {@code bindingString} equal to
"src/test/docker:/some/other/dir", this method returns {@code /path/to/basedir/src/test/docker:/some/other/dir}
</p>
<p>
Given a {@code bindingString} equal to "foo:/some/other/dir", this method returns {@code foo:/some/other/dir},
because {@code foo} is considered to be a <em>named volume</em>, not a relative path.
</p>

@param baseDir the base directory used to resolve relative paths (e.g. beginning with {@code ./}, {@code ../},
               {@code ~}) present in the {@code bindingString}; <em>must</em> be absolute
@param bindingString the volume string from the docker-compose file
@return the volume string, with any relative paths resolved as absolute paths
@throws IllegalArgumentException if the supplied {@code baseDir} is not absolute
src/main/java/io/fabric8/maven/docker/util/VolumeBindingUtil.java