从Docker容器中检索文件的方法是什么?

14

我有一个简单的Dockerfile文件,它会创建一个zip文件,然后我想在zip文件准备好之后进行检索。我的Dockerfile文件如下:

FROM ubuntu

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

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

阅读文档后,我觉得这样做应该可以解决问题,但我无法让它完全正常工作。

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

另外一个问题:是否有可能通过命令行对zip文件进行重命名?

编辑:

这不同于评论中提到的重复的问题,因为虽然他们使用cp从运行的Docker容器中复制文件,但我正在尝试在实例化时挂载目录。


你正在将主机目录映射到容器中的文件?尝试将目录挂载到目录,并在该目录中创建zip文件,这应该可以解决问题(另外,如果没有软件包名称,“apt-get install -y”会执行任何操作吗?) - flagg19
@flagg 我没有将根目录 (/) 映射到当前工作目录 (pwd) 吗?你是对的,应该是 apt-get install -y build-essentials gcc - Pardoner
我对 --mount 命令并不是很熟悉(通常我使用 --volume),但是查看文档 https://docs.docker.com/engine/reference/commandline/service_create/#add-bind-mounts-or-volumes,我认为您缺少了 'type' 的规范(应该是 'bind'),目标应该是一个目录,但是您将其指向了一个文件(/lib64.zip)。 - flagg19
1
可能是从Docker容器复制文件到主机的重复问题。 - David Maze
注意:使用卷的测试方法已经修改。 - Perplexabot
2个回答

30

有多种方法可以做到这一点。

使用docker cp命令:

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

使用Docker卷:

正如你在问题中提到的,你也可以将容器中的路径挂载到主机上。你可以通过指定要挂载点在主机上的位置或不指定挂载点的位置而让Docker选择。这两个方法需要不同的处理方式。

让Docker选择主机挂载位置

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

这个内容将会被放置在你的主机上,位置在这里:

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

让我选择主机挂载位置

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

这将创建一个干净/空的位置,根据命令中定义的位置进行共享。现在您需要修改Dockerfile以将构件复制到此路径,类似于:

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>"]

现在内容将位于您的主机上,位置在此处:

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

我要向@joaofnfernandes表示赞扬,他做得非常好。


2

正如@flagg19所评论的那样,您应该将目录绑定到目录。您可以在容器内创建目录,并且可以覆盖参数。同时执行这两个操作并添加type=bind将会取得巨大的成功:


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

当然,你也可以将Dockerfile中的RUN命令更改为写入/out/lib64.zip而不是/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

无论哪种方式,我建议添加--rm并且去掉--name。在容器完成后不需要保留它。翻译成中文为:

无论哪种方式,我建议添加--rm并且去掉--name。在容器完成后不需要保留它。


我遇到了以下错误:docker: Error response from daemon: create [PATH TO PWD]: "[PATH TO 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. - Pardoner
嗯,奇怪的是错误信息以 / 开头。... create /Users/path/to/my/project: "/Users/path/to/my/project" ... - Pardoner
1
@Pardoner 添加 type=bind,现在你没有类型,默认为 volume,而且 source 使用 type=volume 需要一个卷名称(这就是为什么它会抱怨无效字符,路径不是有效的卷名称),请尝试使用:docker run -d --rm --mount type=bind,source="$(pwd)",target=/out ubuntu-libs - flagg19

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接