"${PWD}" does not work when used with Make on Windows to mount a Docker volume - windows

On a windows machine, I have a Makefile that contains the following instruction:
start_docker:
docker run --rm -p 8888:8888 -it -v "${PWD}":/home/docker/app my_image
When I run make start_docker either in the PowerShell or cmd prompt, I get the following output:
docker run -p 8888:8888 -it -v :/home/docker/app my_image
(note that the output displays a blanck istead of the current path)
And then my local volume is not mounted.
However, if I paste directly docker run --rm -p 8888:8888 -it -v "${PWD}":/home/docker/app my_image the volume is mounted (great!).
I get an error "$(PWD)" 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. if I try to use it in the cmd prompt).
What should I do to start my docker image with make with the correct path in windows (it works smoothly on Linux)?
I also tried ${PWD} and $(pwd), it does not change the issue.

Make doesn't set or use the variable PWD in any way. If it is set, it is either because something in your makefile set it, or because it was inherited from the shell that invoked make.
If you run on a POSIX system like GNU/Linux or MacOS, then the shell will (often, but not always) set the PWD environment variable and make will inherit that. But it's not always right, and not always set. On Windows, the Windows shell (powershell or cmd.exe) do not set this variable, so it's never set.
In short, it's always a portability problem to use PWD.
If you like you could switch to using the GNU make variable CURDIR:
start_docker:
docker run --rm -p 8888:8888 -it -v "${CURDIR}":/home/docker/app my_image
which is set by GNU make when it starts, and so always has a value.

Related

docker run $(pwd) command invalid in Windows

I have to run a simple front-end app on docker with nginx.
I'm following a tutorial that says to run in order:
docker build -t mytest
docker run -v $(pwd):/mnt -p 9090:9090 -w /mnt mytest ./scripts/tests.sh
the first command is ok, the app works fine.
When I run the second one I have an error:
docker: Error response from daemon: create $(pwd): "$(pwd)" 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'.
What is $(pwd)?
I read the doc about -v option but I don't understand the meaning of this variable.
I'm using Windows OS.
The cmd.exe equivalent to $PWD (which is what the tutorial should be recommending instead of the much less efficient $(pwd)) is %cd%
Thus:
docker run -v %cd%:/mnt -p 9090:9090 -w /mnt mytest ./scripts/tests.sh

bash Bad substitution while trying to map directory

I'm trying to map a path to a working directory here is the command code
docker run --runtime=nvidia --privileged -it -v ${/home/segun/tf3d}:/tf3d -w/tf3d/ops tensorflow/tensorflow:custom-op-gpu-ubuntu16
the error is:
bash: ${/home/segun/tf3d}:/tf3d: bad substitution
the documentation says:
docker run --runtime=nvidia --privileged -it -v ${PWD}:/working_dir -w /working_dir tensorflow/tensorflow:custom-op-gpu-ubuntu16
${PWD} is a variable of the current working directory, so if you hardcode you don't need the ${}.
so just instead of ${/home/segun/tf3d} it should be just the path /home/segun/tf3d
or run with ${PWD} in the folder /home/segun/tf3d
also, you miss a space between -w and the working folder path

Why does ";C" get added to the end of my strings in bash when running docker on Windows 10? [duplicate]

I've found some interesting weirdness when trying to mount a docker image on windows.
I created a .sh script that does a mount of the project folder to run our developer environment image. I want one script that every dev can run, regardless of their machine. All it does is runs docker with the current project folder.
#!/usr/bin/env bash
docker run -it --rm -v D:\my\project\folder:/wkDir $IMAGE_TAG yarn dev
Runs okay. Now the plan is to call this script from npm, so I'd like this to work relative to the current folder. Let's try another version.
docker run -it --rm -v $PWD:/wkDir $IMAGE_TAG yarn dev
Fails with:
C:\Program Files\Docker\Docker\Resources\bin\docker.exe: Error response from
daemon: Mount denied:
The source path "D:/my/project/folder;C"
doesn't exist and is not known to Docker.
Wat. What's ;C and where did it come from?
So I do echo $PWD which gives me /d/my/project/folder.
Interesting, so $PWD resolves to the correct path in linux path format, and it seems like docker is trying to translate from that to the correct windows path, except there's this ;C that appears out of nowhere. And the \ are /...
What exactly is going on here?
I get the same result in VSCode's terminal git bash and powershell.
Update: I noticed that running the .sh in VSCode's powershell terminal, opens a separate cmd.exe console window which seems to run the script in git bash. So this might be a git bash issue.
So with some extra digging I found these three threads, related to git-bash mucking up docker mount:
https://forums.docker.com/t/weird-error-under-git-bash-msys-solved/9210
https://github.com/moby/moby/issues/24029#issuecomment-250412919
When I look up mingw's documentation on the path conversion git-bash is using, I find this table of syntax:
http://www.mingw.org/wiki/Posix_path_conversion
One of which outputs in the format: x;x;C:\MinGW\msys\1.0\x. Note the ;C in it. If git-bash is trying to be clever, stuffing up the syntax and outputting a path with this format, this would explain it.
Solution is to escape the path conversion, using by prefixing with /. So the working docker command to run docker from git-bash with present working directory:
docker run -it --rm -v /${PWD}:/wkDir $IMAGE_TAG yarn dev
Mounting the current directory into a Docker container in Windows 10 from Git Bash (MinGW) may fail due to a POSIX path conversion. Any path starting with / is converted to a valid Windows path.
touch test.txt
docker run --rm -v $(pwd):/data busybox ls -la /data/test.txt
# ls: C:/Git/data/test.txt: No such file or directory
Escape the POSIX paths by prefixing with /
To skip the path conversion, all POSIX paths have to be prefixed with the extra leading slash (/), including /$(pwd).
touch test.txt
docker run --rm -v /$(pwd):/data busybox ls -la //data/test.txt
# -rwxr-xr-x 1 root root 0 Jun 22 23:45 //data/test.txt
In Git Bash the path //data/test.txt is not converted and in Linux shells // (leading double slash) is ignored and treated the same way as /.
Disable the path conversion
Disable the POSIX path conversion in Git Bash (MinGW) using MSYS_NO_PATHCONV environment variable.
The path conversion can be disabled at the command level:
touch test.txt
MSYS_NO_PATHCONV=1 docker run --rm -v $(pwd):/data busybox ls -la /data/test.txt
# -rwxr-xr-x 1 root root 0 Jun 22 23:45 /data/test.txt
The path conversion can be disabled at the shell (or system) level:
export MSYS_NO_PATHCONV=1
touch test.txt
docker run --rm -v $(pwd):/data busybox ls -la /data/test.txt
# -rwxr-xr-x 1 root root 0 Jun 22 23:45 /data/test.txt
For me the solution was simply to include a closing slash / at end of any paths.
E.g. instead of
/opt/apache-atlas-2.0.0/bin/atlas_start.py
...use
/opt/apache-atlas-2.0.0/bin/atlas_start.py/
I had the same issue on git bash and not command prompt.
You can instead
docker run -it --rm -v "/${PWD}/D:\my\project\folder":/wkDir $IMAGE_TAG yarn dev
Can you try below command -
docker run -it --rm -v %cd%:/wkDir $IMAGE_TAG yarn dev
I've actually had the same issue. Depending on if you are using Git Bash this command works(using nginx as an example):
docker container run --name container-name -v `pwd -W` /html:/usr/share/nginx/html -p 8000:80 -d nginx
of course you can specify the port and directory as you desire.
Straight worked for me below. just don't use dynamic variable.
docker run --rm -u root -p 8080:8080 -v jenkins-data/:/var/jenkins_home -v /var/run/docker.sock/:/var/run/docker.sock -v /Users/<YOUR USER NAME>/:/home jenkinsci/blueocean

on osx, docker run -v $(pwd):... does not get expanded

On OSX, when running a docker container and mounting the current directory, the expression $(pwd) does not get expanded:
bash
docker run -v $(pwd):/var/mydir image
On the container, /var/mydir remains empty.
I have installed bash-completion via homebrew, and the docker-specific bash completion also.
I see examples of using $(pwd) on OSX all over the place, and yet I cannot make it work.
Please note that the current directory is under /Users, e.g. /Users/joe/projects/demo
Try to test it first:
path=$(pwd); echo ${path}
If that work, then you can add the docker command:
path=$(pwd); docker run -v ${path}:/var/mydir image
Also, if you are executing that command from the host shell (Mac), instead of the docker machine shell (through a docker-machine ssh session), make sure you have executed eval "$(docker-machine env <machinename>)" first.
Using ${PWD}:
docker run -v ${PWD}:/src -w /src golang:1.17 go mod download && go run main.go

Setting environment variables when running docker in detached mode

If I include the following line in /root/.bashrc:
export $A = "AAA"
then when I run the docker container in interactive mode (docker run -i), the $A variable keeps its value. However if I run the container in detached mode I cannot access the variable. Even if I run the container explicitly sourcing the .bashrc like
docker run -d my_image /bin/bash -c "cd /root && source .bashrc && echo $A"
such line produces an empty output.
So, why is this happening? And how can I set the environment variables defined in the .bashrc file?
Any help would be very much appreciated!
The first problem is that the command you are running has $A being interpreted by your hosts shell (not the container shell). On your host, $A is likely black, so your effectively command becomes:
docker run -i my_image /bin/bash -c "cd /root && source .bashrc && echo "
Which does exactly as it says. We can escape the variable so it is sent to the container and properly evaluated there:
docker run -i my_image /bin/bash -c "echo \$A"
But this will also be blank because, although the container is, the shell is not in interactive mode. But we can force it to be:
docker run -i my_image /bin/bash -i -c "echo \$A"
Woohoo, we finally got our desired result. But with an added error from bash because there is no TTY. So, instead of interactive mode, we can just set a psuedo-TTY:
docker run -t my_image /bin/bash -i -c "echo \$A"
After running some tests, it appears that when running a container in detached mode, overidding the default environment variables doesnt always happen the way we want, depending on where you are in the Dockerfile.
As an exemple if, running a container in a detached container like so:
docker run **-d** --name image_name_container image_name
Whatever ENV variables you defined within the Dockerfile takes effect everywhere (read the rest and you will understand what the everywhere means).
example of a simple dockerfile (alpine is just a lighweight linux distribution):
FROM alpine:latest
#declaring a docker env variable and giving it a default value
ENV MY_ENV_VARIABLE dummy_value
#copying two dummy scripts into a place where i can execute them straight away
COPY ./start.sh /usr/sbin
COPY ./not_start.sh /usr/sbin
#in this script i could do: echo $MY_ENV_VARIABLE > /test1.txt
RUN not_start.sh
RUN echo $MY_ENV_VARIABLE > /test2.txt
#in this script i could do: echo $MY_ENV_VARIABLE > /test3.txt
ENTRYPOINT ["start.sh"]
Now if you want to run your container in detached and override some ENV variables, like so:
docker run **-d** -e MY_ENV_VARIABLE=new_value --name image_name_container image_name
Surprise! The var MY_ENV_VARIABLE is only overidden inside the script that is run in the ENTRYPOINT (and i checked, same thing happens if your replace ENTRYPOINT with CMD). It would also be overidden in a subscript that you could call from this start.sh script. But the MY_EV_VARIABLE variables that are called within a RUN dockerfile command or within the dockerfile itself do not get overidden.
In other words we would have $MY_ENV_VARIABLE being replaced by the value dummy_value and new_value depending on if you are in the ENTRYPOINT or not.

Resources