Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve file from docker container?

I have a simple Dockerfile which creates a zip file and I'm trying retrieve the zip file once it is ready. My Dockerfile looks like this:

FROM ubuntu

RUN apt-get update && apt-get install -y build-essentials gcc

ENTRYPOINT ["zip","-r","-9"]
CMD ["/lib64.zip", "/lib64"]

After reading through the docs I fee like something like this should do it but I can't quite get it to work.

docker build -t ubuntu-libs .
docker run -d --name ubuntu-libs --mount source=$(pwd)/,target=/lib64.zip ubuntu-libs

One other side question: Is is possible to rename the zip file from the command line?

Edit:

This is different than the duplicate question mentioned in the comments because while they're using cp to copy file from a running Docker container I'm trying to mount a directory upon instantiation.

like image 946
Pardoner Avatar asked Jun 27 '19 18:06

Pardoner


2 Answers

There are multiple ways to do this.

Using docker cp:

docker cp <container_hash>:/path/to/zip/file.zip /path/on/host/new_name.zip

Using docker volumes:

As you were leading to in your question, you can also mount a path from the container to your host. You can either do this by specifying where on the host you want the mount point to be or don't specify where the mount point is and let docker choose. Both these paths require different approaches.

Let docker choose host mount location

docker volume create random_volume_name
docker run -d --name ubuntu-libs -v random_volume_name:<path/to/mount/in/container> ubuntu-libs

The content will be located on your host, here:

ls -l /var/lib/docker/volumes/random_volume_name/_data/ 

Let me choose host mount location

docker run -d --name ubuntu-libs -v <existing/mount/point/on/host>:<path/to/mount/in/container> ubuntu-libs

This creates a clean/empty location that is shared as per the locations defined in the command. Now you need to modify your Dockerfile to copy the artifacts to this path, something like:

FROM ubuntu

RUN apt-get update && apt-get install -y build-essentials gcc

ENTRYPOINT ["zip","-r","-9"]
CMD ["sh", "-c", "/lib64.zip", "/lib64", "cp", "path/to/zip/file.zip", "<path/to/mount/in/container>"]

The content will now be located on your host, here:

ls -l <existing/mount/point/on/host>

I got to give a shout out to @joaofnfernandes from here, who does a great job explaining.

like image 139
Perplexabot Avatar answered Oct 10 '22 06:10

Perplexabot


As @flagg19 commented, you should be binding a directory onto a directory. You can make up directories inside the container, and you can override the RUN arguments. Doing both plus adding type=bind leads to great success:

docker run -d --rm --mount type=bind,source="$(pwd)",target=/out ubuntu-libs /out/lib64.zip /lib64

Or of course you could change the Dockerfile RUN command to write to /out/lib64.zip instead of /lib64.zip:

FROM ubuntu

RUN apt-get update && apt-get install -y build-essentials gcc && mkdir /out

ENTRYPOINT ["zip","-r","-9"]
CMD ["/out/lib64.zip", "/lib64"]
docker run -d --rm --mount type=bind,source="$(pwd)",target=/out ubuntu-libs

Either way, I recommend adding --rm and getting rid of --name. No need to keep around the container after it's done.

like image 40
John Kugelman Avatar answered Oct 10 '22 07:10

John Kugelman