如何将文件从 dockerfile 复制到主机?

Posted

技术标签:

【中文标题】如何将文件从 dockerfile 复制到主机?【英文标题】:How to copy files from dockerfile to host? 【发布时间】:2016-01-27 09:33:40 【问题描述】:

我想在 dockerfile 构建成功后获取一些文件,但它不会将文件从容器复制到主机。

这意味着当我构建 dockerfile 时,文件已经是主机。

【问题讨论】:

Docker - copy file from container to host 【参考方案1】:

支持将文件“从 Dockerfile”复制到主机。 Dockerfile 只是指定如何构建映像的配方。

构建时,您有机会将文件从主机复制到您正在构建的映像(使用COPY directive 或ADD

你也可以用docker cp从容器(已经docker run'd的镜像)复制文件到主机(实际上cp可以从主机复制到容器也)

如果您想将构建过程中可能已生成的一些文件返回到您的主机(例如 calling a script 和 generates ssl),您可以运行一个容器,从您的主机挂载一个文件夹并执行 cp命令。

例如看这个getcrt script。

docker run -u root --entrypoint=/bin/sh --rm -i -v $HOME/b2d/apache:/apache apache << COMMANDS
pwd
cp crt /apache
cp key /apache
echo Changing owner from \$(id -u):\$(id -g) to $(id -u):$(id -u)
chown -R $(id -u):$(id -u) /apache/crt
chown -R $(id -u):$(id -u) /apache/key
COMMANDS

COMMANDS 之间的所有内容都是在容器上执行的命令,包括在主机$HOME/b2d/apache 文件夹上复制的cp 的命令,以/apache-v $HOME/b2d/apache:/apache 安装在容器内。

这意味着每次您在容器中复制/apache 上的任何内容时,实际上都是在主机上复制$HOME/b2d/apache

【讨论】:

感谢您的回复。太特别了,我试试看。 我们如何通过 dockerfile 实现这一点?? @SudarP 我认为这个 2015 年的答案是说它无法完成?您对此的具体用例是什么? 在某些用例中,您需要在构建时显式地复制回主机,而不是在以后的容器运行时。例如,假设您有一个多阶段构建,其中在一个构建阶段执行一些单元测试并编写测试覆盖率报告。您需要在特定的构建阶段通过 - 失败的测试应该使构建失败,并且不会在以后的容器运行中发生。但您可能还需要重新训练代码覆盖率报告文件以用于任何图像或容器之外的其他用途。 最重要的是,整个过程可以在 CI/CD 系统中运行,在该系统中,为了复制目的,拉取 Docker 容器并在全新的 CI/CD 步骤中运行它是昂贵的输出一个文件 - 你真的需要它发生在构建发生的同一个 CI/CD 过程中,而不是任何以后的容器拉 + 运行。【参考方案2】:

也许你可以从主机上挂载一个文件夹作为一个卷并将文件放在那里?通常挂载的卷可以从容器内写入,除非您在挂载时指定只读选项。

docker run -v $PWD:/<somewritablepath> -w <somewritablepath> <image> <action>

【讨论】:

【参考方案3】:

虽然 Dockerfile 功能不直接支持它,但您可以从构建的 docker 镜像中复制文件。

containerId=$(docker create example:latest)
docker cp "$containerId":/source/path /destination/path
docker rm "$containerId"

【讨论】:

【参考方案4】:

自从 2019 年 7 月 Docker 19.03.0 引入“自定义构建输出”以来,这现在已经成为可能。请参阅有关custom build outputs 的官方文档。

为了能够在构建过程中将构建映像的结果输出到主机中,您需要激活 BuildKit,这是一种较新的推荐向后兼容引擎的方式做构建阶段。请参阅enabling BuildKit 的官方文档。

这可以通过两种方式完成:

    设置环境变量DOCKER_BUILDKIT=1 默认在 docker 引擎中设置它,方法是将 "features": "buildkit": true 添加到配置 json 的根目录中。

来自关于custom build outputs的官方文档:

自定义导出器允许您将构建工件导出为本地文件系统上的文件,而不是 Docker 映像,这对于生成本地二进制文件、代码生成等很有用。

...

本地导出器将生成的构建文件写入客户端的目录。 tar 导出器类似,但将文件写入为单个 tarball (.tar)。

如果不指定类型,则默认为本地exporter的输出目录。

...

仅导出特定文件的常见模式是进行多阶段构建并使用 COPY --from 将所需文件复制到新的暂存阶段。

例如一个示例 Dockerfile

FROM alpine:latest AS stage1
WORKDIR /app
RUN echo "hello world" > output.txt

FROM scratch AS export-stage
COPY --from=stage1 /app/output.txt .

跑步

DOCKER_BUILDKIT=1 docker build --file Dockerfile --output out .

输出的尾部是:

 => [export-stage 1/1] COPY --from=stage1 /app/output.txt .
0.0s
 => exporting to client
0.1s
 => => copying files 45B
0.1s

这会生成一个由RUN 命令创建的本地文件out/output.txt

$ cat out/output.txt
hello world

【讨论】:

这看起来很有希望,但由于某种原因,我也从不同阶段复制了文件。有没有办法只从这个特定阶段而不是其他阶段获得输出? --from 标志用于指定要从中复制的阶段。 2020年这应该是选择的答案!这“是”的方式。 Ben T => 谢谢! 2021 年依然有效 它还在工作【参考方案5】:

使用 Dockerfile 完成 Docker Build,以下对我有用:

在我的设置中,/var/lib/docker/Docker Root Dir:

sudo find /var/lib/docker/ -name DESIRED_FILE -type f | xargs sudo ls -hrt | tail -1 | grep tgz | xargs  -i  sudo cp -v  '' PATH_ON_HOST

【讨论】:

【参考方案6】:

您也可以使用网络。从这个答案的脚本开始:https://***.com/a/58255859/836450

我在我的主机上运行此脚本,位于我想要输出的文件夹中

在我的 docker 里面我有:

运行 apt-get install -y curl 运行 curl -F 'file=@/path/to/file' http://172.17.0.1:44444/

请注意,至少对我而言,172.17.0.1 在构建 dockerfile 时始终是主机的 IP

【讨论】:

以上是关于如何将文件从 dockerfile 复制到主机?的主要内容,如果未能解决你的问题,请参考以下文章

Docker 将文件从 dockerfile 复制到主机

将文件夹从 Dockerfile 复制到主机 [重复]

Dockerfile 将主机用户 UID 和 GID 复制到镜像

无法将中间docker容器文件复制到主机

如何将 4D 数组的一部分从主机内存复制到设备内存?

使用 Docker 文件中的 COPY 将文件夹从 Windows 主机操作系统复制到 Docker 映像中