New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docker cp should support VOLUMEs #1992
Comments
IMHO, volumes should behave this way: when declaring a volume, if the volume is empty on the host, the content of the directory (in the container) will be copied to the volume (on the host) before binding the volume to the container. This means that you could make any directory a volume without breaking the container behavior. |
+1 we really need to implement this. It's a blocker for anyone with an initial db content in the image for example. On Tue, Sep 24, 2013 at 11:34 AM, Jérôme Petazzoni
|
I'm working on this right now. should be done soon |
(Someone on IRC asked more details; so I'll try to explain it better.) Suppose you have a MySQL image. In My proposal is the following: when doing Now, what happens when you do something like Hence the "if empty" condition. If |
For historical value I dug around for the first implementation of that logic in docker's great-granpa: dotcloud circa 2009! https://bitbucket.org/Foi3GraS/dotcloud-fork/src/c0db261cbbef198f0ded934a42dcabe1294a814f/volume/directory.py?at=default#cl-85 (looks like this fork by Foi3GraS is the only remaining trace of the original open-source dotcloud :)
On Tue, Sep 24, 2013 at 13:01, Jérôme Petazzoni <notifications@github.com="mailto:notifications@github.com">> wrote: (Someone on IRC asked more details; so I'll try to explain it better.) Suppose you have a MySQL image. In /var/lib/mysql, it has the initial content of the database (if you're using default paths). Currently, if you do -v /var/lib/mysql, the directory will be mounted as a volume, and the volume will initially be empty. As a result, MySQL won't start. My proposal is the following: when doing -v /var/lib/mysql, initialize the content of the volume with the content of /var/lib/mysql in the image. That way, it will be a volume, but MySQL will start. Now, what happens when you do something like -v /mnt/db:/var/lib/mysql? You're asking Docker to mount /mnt/db (in the host) to /var/lib/mysql (in the container). If you copy the content of /var/lilb/mysql (from the image) to the volume each time you start the container, you will reset the database each time... Which is probably not what you want. Hence the "if empty" condition. If /mnt/db is empty, it will be initialized with the content of /var/lib/mysql. If it contains anything, it won't be touched, and be used as is. — |
Oh, it looks like I hadn't understood the initial question. I thought the issue was " My bad. |
Should I open a separate issue for volume initialization? |
I jumped into this issue thinking it would be a quick fix but it is not. The way volumes are implemented are a little challenging for copying the files. Say you have a volume
Because the container actually has the /data directory and the volume's layer directory has the files you will get a directory /layer copied to your system with the data instead of /data with the data. This is because we tar the directory and contents and the root directory in the volume's path is @jpetazzo @shykes Any ideas on how to solve this? This was my initial thought func (container *Container) Copy(resource string) (Archive, error) {
if err := container.EnsureMounted(); err != nil {
return nil, err
}
rootPath := container.RootfsPath()
// Check if a container has any volumes and if it does, see if the resource
// is inside a volume
if container.Volumes != nil && len(container.Volumes) > 0 {
for volume, volumePath := range container.Volumes {
if filepath.HasPrefix(resource, volume) {
rootPath = volumePath
// Because files in a volume are stored in the layer directory without
// the folder name we have to stripe the volume name from the resource
resource = strings.TrimPrefix(resource, volume)
break
}
}
}
var filter []string
basePath := path.Join(rootPath, resource)
stat, err := os.Stat(basePath)
if err != nil {
return nil, err
}
if !stat.IsDir() {
d, f := path.Split(basePath)
basePath = d
filter = []string{f}
} else {
filter = []string{path.Base(basePath)}
basePath = path.Dir(basePath)
}
return TarFilter(basePath, Uncompressed, filter)
} |
I think it's the way to go; with a couple of caveats:
|
Wouldn't it make more sense to copy the contents of the volume once, at On Tue, Sep 24, 2013 at 2:25 PM, Jérôme Petazzoni
|
Well, if I understand correctly, you can't do the copy orthogonally, |
Ah, right. What if we also made sure they were mounted in docker's On Tue, Sep 24, 2013 at 5:56 PM, Jérôme Petazzoni
|
Assigned myself, this will be implemented after the graph driver changes |
This first part of this is to have docker handled mounting volumes and not rely on lxc. |
What's the status of this? Is this something I can get my hands into? |
This can be easily accomplished now that we are mounting volumes outside of LXC. |
This is the #1 thing I am hoping to see added to docker. Is someone already working on this? If not it might be a reason for me to learn Go. |
I would like to, not sure where to look at the moment. |
I am not sure if the issue I am encountering is a variant of this issue or not and whether the same fix will address it or not, so adding my case for triggering it as an additional test case. Docker file:
Build it:
Run it and create a new file in the volume, or even update an existing one. Leave the shell open initially.
From separate window copy out updated file and it will work.
Now exit container so it is stopped. Run the copy again against the stopped container.
|
@GrahamDumpleton Your issue is resolved handled. |
Closes moby#1992 Docker-DCO-1.0-Signed-off-by: Michael Crosby <crosby.michael@gmail.com> (github: crosbymichael)
This should be closed, as #3472 fixes this. |
afaik that was not ever merged into docker and this is still an issue. On Wed, May 14, 2014 at 7:45 AM, Aleksa Sarai notifications@github.comwrote:
|
confirmed still as an issue for me. I have a volume
|
Confirmed that this still exists in 1.0.0. I got hit by this. |
Confirmed here again too also using my same exact example as before.
|
I was hit by this today.
|
same issue here, what about #3472?
|
Fixes moby#1992 Right now when you `docker cp` a path which is in a volume, the cp itself works, however you end up getting files that are in the container's fs rather than the files in the volume (which is not in the container's fs). This makes it so when you `docker cp` a path that is in a volume it follows the volume to the real path on the host. archive.go has been modified so that when you do `docker cp mydata:/foo .`, and /foo is the volume, the outputed folder is called "foo" instead of the volume ID (because we are telling it to tar up `/var/lib/docker/vfs/dir/<some id>` and not "foo", but the user would be expecting "foo", not the ID Signed-off-by: Brian Goff <cpuguy83@gmail.com>
docker cp seems to be limited to the root/default volume, as confirmed on IRC:
$ cat Dockerfile
FROM ubuntu:precise
MAINTAINER Benjamin Podszun "dar@darklajid.de"
VOLUME /some/volume
RUN touch /some/volume/I_Want_To_Copy_This
CMD /bin/bash
$ docker build .
Uploading context 10240 bytes
Step 1 : FROM ubuntu:precise
Pulling repository ubuntu
---> 8dbd9e392a96layersfrom ubuntu, endpoint: https://cdn-registry-1.docker.io/v1/
Step 2 : MAINTAINER Benjamin Podszun "dar@darklajid.de"
---> Using cache
---> c950832bf997
Step 3 : VOLUME /some/volume
---> Running in f9b8fc1901f2
---> 56106cf843d5
Step 4 : RUN touch /some/volume/I_Want_To_Copy_This
---> Running in 31eca80e094d
---> 2cb2858fedee
Step 5 : CMD /bin/bash
---> Running in af26bafd07ba
---> 4e0f6538a826
Successfully built 4e0f6538a826
$ docker run -i -t 4e0f6538a826
root@d787a64f78f9:/#
$ docker cp d787a64f78f9:/some/volume/I_Want_To_Copy_This .
2013/09/24 17:12:11 Error: stat /var/lib/docker/containers/d787a64f78f94e88abcdda2c8224c3ecfface23d783c4308f08ef1a3367d2ae1/rootfs/some/volume/I_Want_To_Copy_This: no such file or directory
The text was updated successfully, but these errors were encountered: