将文件从Docker容器复制到主机

2797

我在考虑使用Docker在持续集成(CI)服务器上构建我的依赖项,这样我就不必在代理上安装所有运行时和库。

为了实现这一点,我需要将在容器内构建的构建工件复制回主机。这可能吗?


4
使用最新版本的Docker,您可以使用buildkit的--output选项。DOCKER_BUILDKIT=1 docker build -f Dockerfile --target=testresult --output outhttps://github.com/moby/buildkit#local-directory - Alex Punnen
3
补充Alex的答案:DOCKER_BUILDKIT=1是一个环境设置,若要使用buildkit作为构建引擎,则必须将DOCKER_BUILDKIT设置为1。更多信息请查阅Docker网站:https://docs.docker.com/engine/reference/builder/#buildkit - Ryan Barrett
将我尝试访问的目录添加到 docker-compose.ymlvolumes 部分中,对我来说非常有效:- ./srv/reports:/srv/reports:delegated - Akaisteph7
27个回答

18

随着Docker 19.03的发布,你可以跳过创建容器甚至构建镜像。在基于BuildKit的构建中有一个选项可以改变输出目的地。您可以使用此选项将构建结果写入本地目录而不是镜像中。例如,这里是一个Go二进制文件的构建:

$ ls
Dockerfile  go.mod  main.go

$ cat Dockerfile
FROM golang:1.12-alpine as dev
RUN apk add --no-cache git ca-certificates
RUN adduser -D appuser
WORKDIR /src
COPY . /src/
CMD CGO_ENABLED=0 go build -o app . && ./app

FROM dev as build
RUN CGO_ENABLED=0 go build -o app .
USER appuser
CMD [ "./app" ]

FROM scratch as release
COPY --from=build /etc/passwd /etc/group /etc/
COPY --from=build /src/app /app
USER appuser
CMD [ "/app" ]

FROM scratch as artifact
COPY --from=build /src/app /app

FROM release

从上面的Dockerfile中,我正在构建只包括我想要导出的文件的“artifact”阶段。新引入的“--output”标志让我将这些文件写入本地目录而不是镜像。必须使用随19.03一起提供的BuildKit引擎执行此操作。
$ DOCKER_BUILDKIT=1 docker build --target artifact --output type=local,dest=. .
[+] Building 43.5s (12/12) FINISHED
 => [internal] load build definition from Dockerfile                                                                              0.7s
 => => transferring dockerfile: 572B                                                                                              0.0s
 => [internal] load .dockerignore                                                                                                 0.5s
 => => transferring context: 2B                                                                                                   0.0s
 => [internal] load metadata for docker.io/library/golang:1.12-alpine                                                             0.9s
 => [dev 1/5] FROM docker.io/library/golang:1.12-alpine@sha256:50deab916cce57a792cd88af3479d127a9ec571692a1a9c22109532c0d0499a0  22.5s
 => => resolve docker.io/library/golang:1.12-alpine@sha256:50deab916cce57a792cd88af3479d127a9ec571692a1a9c22109532c0d0499a0       0.0s
 => => sha256:1ec62c064901392a6722bb47a377c01a381f4482b1ce094b6d28682b6b6279fd 155B / 155B                                        0.3s
 => => sha256:50deab916cce57a792cd88af3479d127a9ec571692a1a9c22109532c0d0499a0 1.65kB / 1.65kB                                    0.0s
 => => sha256:2ecd820bec717ec5a8cdc2a1ae04887ed9b46c996f515abc481cac43a12628da 1.36kB / 1.36kB                                    0.0s
 => => sha256:6a17089e5a3afc489e5b6c118cd46eda66b2d5361f309d8d4b0dcac268a47b13 3.81kB / 3.81kB                                    0.0s
 => => sha256:89d9c30c1d48bac627e5c6cb0d1ed1eec28e7dbdfbcc04712e4c79c0f83faf17 2.79MB / 2.79MB                                    0.6s
 => => sha256:8ef94372a977c02d425f12c8cbda5416e372b7a869a6c2b20342c589dba3eae5 301.72kB / 301.72kB                                0.4s
 => => sha256:025f14a3d97f92c07a07446e7ea8933b86068d00da9e252cf3277e9347b6fe69 125.33MB / 125.33MB                               13.7s
 => => sha256:7047deb9704134ff71c99791be3f6474bb45bc3971dde9257ef9186d7cb156db 125B / 125B                                        0.8s
 => => extracting sha256:89d9c30c1d48bac627e5c6cb0d1ed1eec28e7dbdfbcc04712e4c79c0f83faf17                                         0.2s
 => => extracting sha256:8ef94372a977c02d425f12c8cbda5416e372b7a869a6c2b20342c589dba3eae5                                         0.1s
 => => extracting sha256:1ec62c064901392a6722bb47a377c01a381f4482b1ce094b6d28682b6b6279fd                                         0.0s
 => => extracting sha256:025f14a3d97f92c07a07446e7ea8933b86068d00da9e252cf3277e9347b6fe69                                         5.2s
 => => extracting sha256:7047deb9704134ff71c99791be3f6474bb45bc3971dde9257ef9186d7cb156db                                         0.0s
 => [internal] load build context                                                                                                 0.3s
 => => transferring context: 2.11kB                                                                                               0.0s
 => [dev 2/5] RUN apk add --no-cache git ca-certificates                                                                          3.8s
 => [dev 3/5] RUN adduser -D appuser                                                                                              1.7s
 => [dev 4/5] WORKDIR /src                                                                                                        0.5s
 => [dev 5/5] COPY . /src/                                                                                                        0.4s
 => [build 1/1] RUN CGO_ENABLED=0 go build -o app .                                                                              11.6s
 => [artifact 1/1] COPY --from=build /src/app /app                                                                                0.5s
 => exporting to client                                                                                                           0.1s
 => => copying files 10.00MB                                                                                                      0.1s

构建完成后,app 二进制文件已导出:

$ ls
Dockerfile  app  go.mod  main.go

$ ./app
Ready to receive requests on port 8080

Docker在其上游的BuildKit仓库中记录了--output标志的其他选项:https://github.com/moby/buildkit#output


标准构建缓存不用于具有输出的构建,这是不好的。 - burtsevyg
@burtsevyg Buildkit是一种不同的构建工具,使用不同的缓存环境。它的缓存效率更高。 - BMitch
它可以帮助使用容器构建二进制文件并将其发布到本地主机。 - Aisuko

12

docker cp [选项] 容器名或ID:源路径 目标路径 从容器复制数据到主机。

例如:docker cp test:/opt/file1 /etc/

反之,从主机复制数据到容器:

docker cp [选项] 源路径 容器名或ID:目标路径


10

我为那些使用Docker for Mac的人发布这篇内容。以下是对我有效的方法:

 $ mkdir mybackup # local directory on Mac

 $ docker run --rm --volumes-from <containerid> \
    -v `pwd`/mybackup:/backup \  
    busybox \                   
    cp /data/mydata.txt /backup 
请注意,当我使用-v挂载时,backup目录会自动创建。
希望这对某个人有用。 :)

如果您使用docker-compose,volumes-from在版本3及以上已被弃用。 - Alejandro Galera
补充mulg0r的评论,参见https://dev59.com/SlcO5IYBdhLWcg3woDBT#45495380 - 在v.3中,您需要在config.yml的根目录下放置一个“volumes”命令,以便多个容器可以访问卷。 - ToolmakerSteve

9
另一个好的选择是先构建容器,然后使用-c标志和shell解释器运行它以执行一些命令。
docker run --rm -i -v <host_path>:<container_path> <mydockerimage> /bin/sh -c "cp -r /tmp/homework/* <container_path>"

上述命令的功能如下: -i = 以交互模式运行容器 --rm = 执行后删除容器 -v = 共享文件夹,将主机路径共享到容器路径
最后,/bin/sh -c 命令可以让你将一个命令作为参数引入,该命令将会将你的作业文件复制到容器路径。
希望这些额外的信息能对您有所帮助。

7

7
我使用PowerShell(管理员权限)通过以下命令完成了此操作。
docker cp {container id}:{container path}/error.html  C:\\error.html

示例

docker cp ff3a6608467d:/var/www/app/error.html  C:\\error.html

7
sudo docker cp <running_container_id>:<full_file_path_in_container> <path_on_local_machine>

例子:

sudo docker cp d8a17dfc455f:/tests/reports /home/acbcb/Documents/abc

6

如果您只想从一个镜像(而不是一个正在运行的容器)中拉取文件,可以执行以下操作:

docker run --rm <image> cat <source> > <local_dest>

这将启动容器,写入新文件,然后删除容器。但是,缺点是文件权限和修改日期将不会被保留。


4
最简单的方法是创建一个容器,获取ID,然后从那里复制。
IMAGE_TAG=my-image-tag
container=$(docker create ${IMAGE_TAG})
docker cp ${container}:/src-path ./dst-path/

4
作为一个更通用的解决方案,有一个CloudBees插件可以在Docker容器内构建Jenkins。您可以从Docker注册表中选择要使用的映像或定义要构建和使用的Dockerfile。
它将工作区作为卷(具有适当的用户)挂载到容器中,并将其设置为您的工作目录,在容器内执行您请求的任何命令。 如果您更喜欢代码而不是UI,则还可以使用docker-workflow插件来完成此操作,使用image.inside() {}命令。
基本上,所有这些都被集成到您的CI/CD服务器中,然后进行了一些修改。

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