Cannot mount volume in docker container when directory name contains colon - docker

I cannot mount a volume to a docker container when the directory name contains a colon (:)
The name of the directory is 2012-08-05-00:16:37 and I prefer not renaming the directory. I tried:
docker run -it --name test1 \
-v /host_system_path/2012-08-05-00\:16\:37/:/container_path/2012-08-05-00\:16\:37/
image_name
I get the error:
docker: Error response from daemon: invalid bind mount spec.See
'docker run --help'.
If I rename the directory without spaces or only with hyphens, then the directory is mounted into the container without any issues. Can someone point out how can I solve the problem when the directory contains a colon.
I am on Ubuntu:16.04 and Docker version 17.06.0-ce.

Colons are currently not supported when specifying directory mappings via -v, and it seems you cannot escape them either.
You need to leverage --mount instead:
docker run ... --mount type=bind,source=/some:colon:file,destination=/container-path ...
In the worst of cases, you may of course alternatively still work around this limitation with a temporary system link (ln -s) or rename the target directory temporarily.

It's an open issue with Docker. But in your case, why would docker run -it --name test1 -v /host_system_path:/container_path image_name not be sufficient?

Related

Docker: mount path must be absolute when using volume

I am on a windows host and using git bash.
My goal is to create an alias for Jekyll on my git bash: run the docker image instead of installing all the dependencies. I also want to store the "gems" in a local docker volume.
I would like to use the image jekyll/jekyll:stable and the image has a readme here.
This is the alias that I have in my aliases.sh:
alias jekyll='winpty docker run --rm --volume=$PWD:/srv/jekyll --mount type=volume,src=gems,dst=/usr/gem,volume-driver=local -it jekyll/jekyll:stable'
Issuing jekyll results in:
docker: Error response from daemon: invalid mount config for type "volume": invalid mount path: 'C:/Program Files/Git/usr/gem' mount path must be absolute. See 'docker run --help'.
I don't understand: I am trying to mount a volume, not a bind mount. I have also tried to use the more simplistic "-v" syntax, same result. Is my docker trying to mount gems as a (directory) bind mount?
I also tried to debug this with bash set -x, the actual command issued was winpty docker run --rm --volume=/h/:/srv/jekyll --mount type=volume,src=gems,dst=/usr/gem,volume-driver=local -it jekyll/jekyll:stable which looks OK.
UPDATE: It seems that perhaps the /usr destination (in container) is being translated as C:/Program Files/Git/usr/gem which is wrong... I'd need to somehow insert a literal /usr/ in my command.

Trying to run "comitted" Docker image, get "cannot mount volume over existing file, file exists"

I am developing a Docker image. I started with a base image and was working inside it interactively, using bash. I installed a bunch of stuff, and the install (which included compiling a lot of code) took over 20 minutes, so to save my work, I used:
$ docker commit 0f08ac958391 myproject:wip
Now when I try to run the image:
$ docker run --rm -it myproject:wip
docker: Error response from daemon: cannot mount volume over existing file, file exists /var/lib/docker/overlay2/95aa9a9ea7cc0b1ba302adbd287e4d7059ee4fbe64183404df3bc65df332ee63/merged/run/host-services/ssh-auth.sock.
What is going on? How do I fix this?
Note about related/duplicate questions: while there are other questions about this error message, none of the answers directly explain why the error happens in this situation or what to do about it. In fact, most of the questions have no answers at all.
When I ran the base image, I included a mount for the SSH agent socket:
$ docker run --rm -it -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock myproject:dev /bin/bash
This bind mounts a file from the host (actually the Docker daemon VM) to a file in the Docker container. When I committed the running image, the image contained the file /run/host-services/ssh-auth.sock. The image also contained an empty volume reference to /run/host-services/ssh-auth.sock. This means that when I ran
$ docker run --rm -it myproject:wip
It was equivalent to running
$ docker run -v /run/host-services/ssh-auth.sock --rm -it myproject:wip
Unfortunately, what that command does is create an anonymous volume and mount it into the directory /run/host-services/ssh-auth.sock in the container. This works if the container has such a directory or even if it does not. What causes it to fail is if the target name is taken up by a file. Docker will not mount a volume over a file.
The solution is to explicitly provide a mapping from a host file to the target volume. Any host file will do, but in my case it is best to use the original. So this works:
docker run --rm -it -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock myproject:wip

Local volume includes invalid characters

I am trying to mount local directory to docker container. Here is the command that i use:
docker run -itd --rm --name chatbot --mount source="$(pwd)",target=/instagram-dm-webhook-service chatbot:12
Where current working dir is: /home/user/instagram-dm-webhook-service
I get this error:
"/home/user/instagram-dm-webhook-service" 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.
So if i understand this, having dash character in path is ok. Where could be the problem?
Interestingly adding only this didn't work either, / here "/$(pwd)"
volume: mounts a managed volume into the container.
bind: bind-mounts a directory or file from the host into the container.
for more details on mount types - https://docs.docker.com/engine/reference/commandline/service_create/#add-bind-mounts-or-volumes
So you need to explicitly add the mount type to bind for mounting a directory.
docker run -it --mount type=bind,source="/$(pwd)",target=/root ubuntu:18.04 /bin/bash
root#eda980649055:/# cd /root
root#eda980649055:~# ls
Jenkinsfile.migrate LICENSE.txt README.md pom.xml src target
You need to put a / before $(pwd)
docker run -itd --rm --name chatbot --mount source="/$(pwd)",target=/instagram-dm-webhook-service chatbot:12

Dockerfile : How to mount host directory in container path?

If i have inside my localhost a log folder at:
/var
/logs
apache.logs
elasticsearch.logs
etc...
And i want to mount /var/logs directory of my host, into a path inside a Docker container, like /usr/var/logs/ , how do i do that within a dockerfile ? So each time a log file is updated, it would be accessible within the container too.
Thank you
You can not mount a volumn in Dockerfile
Because:
Dockerfile will build an image, image is independent on each machine host.
Image should be run everywhere on the same platform for example on linux platform it can be running on fedora, centos, ubuntu, redhat...etc
So you just mount volumn in to the container only. because container will be run on specify machine host.
Hope you understand it. Sorry for my bad English.
You can achieve it in two ways - https://docs.docker.com/storage/bind-mounts/
--mount
$ docker run -d -it --name devtest --mount type=bind,source=/var/logs,target=/usr/var/logs image:tag
-v
$ docker run -d -it --name devtest -v /var/logs:/usr/var/logs image:tag
Try -v option of docker run command.
docker run -itd -v /var/logs:/usr/var/logs image-name
This will mount /var/logs directory of host on to /usr/var/logs directory of container.
Hope this helps.
Update:
To mount directory with source and dest in dockerfile make use of this hack (Not 100% sure though).
RUN --mount=target=/usr/var/logs,type=bind,source=/var/logs

How to re-mount a docker volume without overriding existing files?

When running Docker, you can mount files and directories using the --volume option. E.g.:
docker run --volume /remote ./local myimage
I'm running a docker image that defines VOLUMESs in the Dockerfile. I need to access a config file that happens to be inside one of the defined volumes. I'd like to have that file "synced" on the host so that I can edit it. I know I could run docker exec ..., but I hope to circumvent that overhead for only editing one file. I found out that the volumes created by the VOLUMES line are stored in /var/lib/docker/volumes/<HASH>/_data.
Using docker inspect I was able to find the directory that is mounted:
docker inspect gitlab-runner | grep -B 1 '"Destination": "/etc/gitlab-runner"' | head -n 1 | cut -d '"' -f 4
Output:
/var/lib/docker/volumes/9c233c085c36380c6c33035222c16e5d061368c5060cc81dda2a9a713a2b2b3b/_data
So the question is:
Is there a way to re-mount volumes defined in an image? OR to somehow get the directory easier than my oneliner above?
EDIT after comments by zeppelin I've tried rebinding the volume with no success:
$ mkdir etc
$ docker run -d --name test1 gitlab/gitlab-runner
$ docker run -d --name test2 -v ~/etc:/etc/gitlab-runner gitlab/gitlab-runner
$ docker exec test1 ls /etc/gitlab-runner/
certs
config.toml
$ docker exec test2 ls /etc/gitlab-runner/
# empty. no files
$ ls etc
# also empty
docker inspect shows correctly that the volume is bound to ~/etc, but the files inside the container at /etc/gitlab-runner/ seem lost.
$ docker run -d --name test1 gitlab/gitlab-runner
$ docker run -d --name test2 -v ~/etc:/etc/gitlab-runner gitlab/gitlab-runner
You've got two different volume types there. One I call an anonymous volume (a very long uuid visible when you run docker volume ls). The second is a host volume or bind mount that maps a directory on the host directly into the container. So each container you spun up is looking at different places.
Anonymous volumes and named volumes (docker run -d -v mydata:/etc/gitlab-runner gitlab/gitlab-runner) get initialized to the contents of the image at that directory location. This initialization only happens when the volume is empty and is mounted into a new container. Host volumes, as you've seen, only get the contents of the host filesystem, even if it's empty at that location.
With that background, the short answer to your question is no, you cannot mount a file inside the container back out to your host. But you can copy the file out with several methods, assuming you don't overlay the source of the file with a host volume mount. With a running container, there's the docker cp command. Personally, I like:
docker run --rm -v ~/etc:/target gitlab/gitlab-runner \
cp -av /etc/gitlab-runner/. /target/.
If you have a named volume with data you want to copy in or out, you can use any image with the tools you need to do the copy:
docker run --rm -v mydata:/source -v ~/etc:/target busybox \
cp -av /source/. /target/.
Try to avoid modifying data inside a container from the host directly, much nicer is when you wrap your task into another container that you then start with "--volumes-from" option when possible in your case.
Not sure I understood your problem, anyway, as for the documentation you mention,
The VOLUME instruction creates a mount point with the specified name
and marks it as holding externally mounted volumes from native host or
other containers. [...] The docker run command initializes the newly
created volume with any data that exists at the specified location
within the base image.
So, following the example Dockerfile , after having built the image
docker build -t mytest .
and having the container running
docker run -d -ti --name mytestcontainer mytest /bin/bash
you can access it from the container itself, e.g.
docker exec -ti mytestcontainer ls -l /myvol/greeting
docker exec -ti mytestcontainer cat /myvol/greeting
Hope it helps.

Resources