bash Bad substitution while trying to map directory - bash

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

Related

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

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.

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

Access a bash script variable outside the docker container in which the script is running

I have a bash script running inside a docker container. In this script, I set the value of some variable.
Can I somehow access the value of this variable outside the container?
I tried to make the variable "global" but could not figure out how to do it. Is it a good idea to make the required variable an environment variable inside the container?
How to reproduce
Create a bash script called temp.sh with the following contents:
a=$RANDOM
Now, run this file in a docker container as follows:
docker run -it --rm -v $(pwd):/opt alpine sh -c "sh /opt/temp.sh"
Desired behaviour: To be able to access the variable a outside the docker container
Credit: This comment by Mark
I mounted a directory on the docker filesystem using
docker run -v <host-file-system-directory>:<docker-file-system-directory>
In the bash script, I added
echo "$variable" >docker-file-system-directory/variable.txt
As I had mounted a host filesystem directory on the docker filesystem, I can still access variable.txt simply using cat <host-file-system-directory>/variable.txt
Note that docker-file-system-directory must be an absolute path, and not a relative path.
One way of achieving that is using docker exec, if your container is running and has access to bash.
#!/usr/bin/env bash
set -x
yourContainerName="testContainerName"
test=$(docker exec -i "${yourContainerName}" bash <<EOF
# do some work here e.g. execute your script
testVar="thisIsTest" # the value we want to access outside of container
echo \$testVar
EOF
)
echo $test
We pass a multiline script to docker container, which in the end echo's the value we need. This value is then accessible from shell that executed docker exec.
Output looks like this:
++ docker exec -i testContainerName bash
+ test=thisIsTest
+ echo thisIsTest
thisIsTest

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

'mv' command throwing error but executing fine in docker

When I execute the following command (which moves all files with the .txt and .sbreaks extension to another folder):
sudo docker exec name mv xyz/data/outputs/*.{sbreaks,txt} <>/data/spare
I get the following error:
mv: cannot stat ‘xyz/data/outputs/*.sbreaks’: No such file or directory
mv: cannot stat ‘xyz/data/outputs/*.txt’: No such file or directory
But, when I go into docker via sudo docker exec -it name bash and execute the same command: mv xyz/data/outputs/*.{sbreaks,txt} xyz/data/spare, it executes fine.
What am I doing wrong here?
PS: Both local and the Docker container are ubuntu environments
That is because the * is expanded by a shell program (i.e. bash). (Psst, this is typical interview question).
So pass your command to a shell and let it launch the mv for you:
sudo docker exec cypher bash -c 'mv xyz/data/outputs/*.{sbreaks,txt} .......'
When you do docker exec some_program some_param, docker searches for some_program and executes it directly without doing anything extra, and just pass some_param as a parameter (a star in your case). mv expects real file names, and not *.

Resources