How can I add a volume to an existing Docker container?
DockerDocker Problem Overview
I have a Docker container that I've created simply by installing Docker on Ubuntu and doing:
sudo docker run -i -t ubuntu /bin/bash
I immediately started installing Java and some other tools, spent some time with it, and stopped the container by
exit
Then I wanted to add a volume and realised that this is not as straightforward as I thought it would be. If I use sudo docker -v /somedir run ...
then I end up with a fresh new container, so I'd have to install Java and do what I've already done before just to arrive at a container with a mounted volume.
All the documentation about mounting a folder from the host seems to imply that mounting a volume is something that can be done when creating a container. So the only option I have to avoid reconfiguring a new container from scratch is to commit the existing container to a repository and use that as the basis of a new one whilst mounting the volume.
Is this indeed the only way to add a volume to an existing container?
Docker Solutions
Solution 1 - Docker
You can commit your existing container (that is create a new image from container’s changes) and then run it with your new mounts.
Example:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5a8f89adeead ubuntu:14.04 "/bin/bash" About a minute ago Exited (0) About a minute ago agitated_newton
$ docker commit 5a8f89adeead newimagename
$ docker run -ti -v "$PWD/somedir":/somedir newimagename /bin/bash
If it's all OK, stop your old container, and use this new one.
That´s it :)
Solution 2 - Docker
We don't have any way to add volume in running container, but to achieve this objective you may use the below commands:
Copy files/folders between a container and the local filesystem:
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
For reference see:
Solution 3 - Docker
I've successfully mount /home/<user-name>
folder of my host to the /mnt
folder of the existing (not running) container. You can do it in the following way:
-
Open configuration file corresponding to the stopped container, which can be found at
/var/lib/docker/containers/99d...1fb/config.v2.json
(may beconfig.json
for older versions of docker). -
Find
MountPoints
section, which was empty in my case:"MountPoints":{}
. Next replace the contents with something like this (you can copy proper contents from another container with proper settings):
"MountPoints":{"/mnt":{"Source":"/home/<user-name>","Destination":"/mnt","RW":true,"Name":"","Driver":"","Type":"bind","Propagation":"rprivate","Spec":{"Type":"bind","Source":"/home/<user-name>","Target":"/mnt"},"SkipMountpointCreation":false}}
or the same (formatted):
"MountPoints": {
"/mnt": {
"Source": "/home/<user-name>",
"Destination": "/mnt",
"RW": true,
"Name": "",
"Driver": "",
"Type": "bind",
"Propagation": "rprivate",
"Spec": {
"Type": "bind",
"Source": "/home/<user-name>",
"Target": "/mnt"
},
"SkipMountpointCreation": false
}
}
- Restart the docker service:
service docker restart
This works for me with Ubuntu 18.04.1 and Docker 18.09.0
Solution 4 - Docker
Jérôme Petazzoni has a pretty interesting blog post on how to Attach a volume to a container while it is running. This isn't something that's built into Docker out of the box, but possible to accomplish.
As he also points out
>This will not work on filesystems which are not based on block devices. > >It will only work if /proc/mounts correctly lists the block device node (which, as we saw above, is not necessarily true). > >Also, I only tested this on my local environment; I didn’t even try on a cloud instance or anything like that
YMMV
Solution 5 - Docker
Unfortunately the switch option to mount a volume is only found in the run
command.
docker run --help
-v, --volume list Bind mount a volume (default [])
There is a way you can work around this though so you won't have to reinstall the applications you've already set up on your container.
- Export your container
docker container export -o ./myimage.docker mycontainer
- Import as an image
docker import ./myimage.docker myimage
- Then
docker run -i -t -v /somedir --name mycontainer myimage /bin/bash
Solution 6 - Docker
A note for using Docker Windows containers after I had to look for this problem for a long time!
Condiditions:
- Windows 10
- Docker Desktop (latest version)
- using Docker Windows Container for image microsoft/mssql-server-windows-developer
Problem:
- I wanted to mount a host dictionary into my windows container.
Solution as partially discripted here:
- create docker container
docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y microsoft/mssql-server-windows-developer
- go to command shell in container
docker exec -it <CONTAINERID> cmd.exe
- create DIR
mkdir DirForMount
- stop container
docker container stop <CONTAINERID>
- commit container
docker commit <CONTAINERID> <NEWIMAGENAME>
- delete old container
docker container rm <CONTAINERID>
- create new container with new image and volume mounting
docker run -d -p 1433:1433 -e sa_password=<STRONG_PASSWORD> -e ACCEPT_EULA=Y -v C:\DirToMount:C:\DirForMount <NEWIMAGENAME>
After this i solved this problem on docker windows containers.
Solution 7 - Docker
My answer will be little different. You can stop your container, add the volume and restart it. How to do it, follow the steps.
docker volume create ubuntu-volume
docker stop <container-name>
sudo docker run -i -t --mount source=ubuntu-volume,target=<target-path-in-container> ubuntu /bin/bash
Solution 8 - Docker
Use symlink to the already mounted drive:
ln -s Source_path targer_path_which_is_already_mounted_on_the_running_docker
Solution 9 - Docker
The best way is to copy all the files and folders inside a directory on your local file system by: docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH
SRC_PATH
is on container
DEST_PATH
is on localhost
Then do docker-compose down
attach a volume to the same DEST_PATH
and run Docker containers by using docker-compose up -d
Add volume by following in docker-compose.yml
volumes:
- DEST_PATH:SRC_PATH