rancher-desktop icon indicating copy to clipboard operation
rancher-desktop copied to clipboard

Mounts with type bind will not bind single files correctly in wsl

Open madovaltech opened this issue 1 year ago • 1 comments

Actual Behavior

I expect docker -v and docker --mount to both be able to mount "single files" from the host.

However right now this only works with the "-v" option. A script I have to use, does single file mounting within a composer file.

OS: windows container-engine: docker wsl: ubuntu rancher-desktop version: 1.5.1

Steps to Reproduce

#! /bin/bash

cat <<EOT > echo.sh
#! /bin/bash
echo "Sucessfull bind mount!"
EOT

chmod 777 echo.sh

docker run -it -d \
 --name 'bind-v' \
 -v $PWD/echo.sh:/echo.sh \
 ubuntu sleep infinity

docker run -it -d \
    --name 'bind-mount' \
    --mount type=bind,source=$PWD/echo.sh,target=/echo.sh \
    ubuntu sleep infinity

# wrong behavior; shows a directory
docker exec -it bind-mount sh -c "ls -lha /echo.sh"

#shows the file which is identical to the file from the host
docker exec -it bind-v sh -c "ls -lha /echo.sh"

docker rm --force bind-mount
docker rm --force bind-v

Result

A single file gets mounted as directory

+ docker exec -it bind-mount sh -c 'ls -lha /echo.sh'
total 4.0K
drwx------ 2 root root   40 Aug 19 13:05 .
drwxr-xr-x 1 root root 4.0K Aug 19 13:05 ..
+ docker exec -it bind-v sh -c 'ls -lha /echo.sh'
-rwxrwxrwx 1 1000 1000 43 Aug 19 13:05 /echo.sh

Expected Behavior

I want that the single file gets mounted as the file from my host environment.

Additional Information

Also reproducible via docker-compose file:

version: '3.9'
services:
  file-mount-test:
    image: ubuntu
    volumes:
      - type: bind
        source: ./echo.sh
        target: /echo.sh
    command: /echo.sh

Here is the complete file I used for analyzing and reproducing the issue:

#!/bin/bash

docker rm --force bind-mount
docker rm --force bind-v

cat <<EOT > echo.sh
#! /bin/bash
echo "Sucessfull bind mount!"
EOT

chmod 777 echo.sh

docker run -it -d \
 --name 'bind-v' \
 -v $PWD/echo.sh:/echo.sh \
 ubuntu sleep infinity

docker run -it -d \
    --name 'bind-mount' \
    --mount type=bind,source=$PWD/echo.sh,target=/echo.sh \
    ubuntu sleep infinity

# Bind Mount
echo 'bind-v Binds'
docker inspect bind-v | jq '.[].HostConfig.Binds'
echo 'bind-mount Binds'
docker inspect bind-mount | jq '.[].HostConfig.Binds'

# Volume Mount
echo 'bind-v Binds'
docker inspect bind-v | jq '.[].Mounts'
echo 'bind-mount Binds'
docker inspect bind-mount | jq '.[].Mounts'

set -x

docker exec -it bind-mount sh -c "ls -lha /echo.sh"
docker exec -it bind-v sh -c "ls -lha /echo.sh"

#docker rm --force bind-mount
#docker rm --force bind-v

Rancher Desktop Version

1.5.1

Rancher Desktop K8s Version

I dont know

Which container engine are you using?

moby (docker cli)

What operating system are you using?

Windows

Operating System / Build Version

Windows 10

What CPU architecture are you using?

x64

Linux only: what package format did you use to install Rancher Desktop?

No response

Windows User Only

Not relevant to this issue I think. VPN was not running,while I was testing it.

madovaltech avatar Aug 19 '22 13:08 madovaltech

Thanks for the helpful and detailed bug report! I was able to reproduce this on my Windows 10 machine. We'll work on it when we get a chance - PRs are also welcome :)

adamkpickering avatar Aug 22 '22 20:08 adamkpickering

Confirming. -v /run/docker.sock:/run/docker.sock works every time, --mount source=/run/docker.sock,target=/run/docker.sock,type=bind never works and mounts an empty directory (owned by root.root, mode 700) instead. Also --mount sometimes fails randomly with the same problem, mounting an empty directory instead.

jan-hudec avatar Sep 06 '22 08:09 jan-hudec

Workaround

I wrote this hacky bash script that translates --mount to -v when they are binds without extra options. Dropped it into my WSL install as /usr/local/bin/docker (fortunately rancher-desktop adds itself to the end of PATH) and devcontainers started through WSL now get their docker sockets and docker configs all right.

#!/bin/bash
set -eu

nextdocker=$(which -a docker|tail +2|head -1)

args=()
was_mount=''
for arg in "$@"; do
    if [[ "$arg" == '--mount' ]]; then
        was_mount=yes
    else
        if [[ "$was_mount" == yes ]]; then
            declare -A parts=()
            unset s t
            typ=''
            ro=''
            ifs="$IFS"
            IFS=,
            for part in $arg; do
                case $part in
                    src=*|source=*) s="${part#*=}";;
                    dst=*|destination=*|target=*) t="${part#*=}";;
                    type=bind) typ="${typ}bind";;
                    readonly|readonly=true|readonly=1|ro|ro=true|ro=1) ro=':ro';;
                    *) typ=unknown;;
                esac
            done
            IFS="$ifs"
            if [[ "$typ" == bind ]]; then
                args+=('-v')
                args+=("$s:$t$ro")
            else
                args+=('--mount')
                args+=($arg)
            fi
        else
            args+=("$arg")
        fi
        was_mount=''
    fi
done

exec "$nextdocker" "${args[@]}"

jan-hudec avatar Sep 07 '22 16:09 jan-hudec