繁体   English   中英

如何使用docker cp将多个文件从容器复制到主机

[英]How to copy multiple files from container to host using docker cp

我想使用通配符从容器中的目录中选择多个文件,并使用 docker cp 将这些文件从容器复制到 docker 主机。

我找不到 docker cp 是否支持使用通配符。

docker cp fd87af99b650:/foo/metrics.csv* /root/metrices_testing/

这导致错误metrics.csv*: no such file or directory

我遇到了一个示例,其中for loop用于选择几个文件然后发送到容器,但我想将文件从容器传输到主机,并希望在 docker 主机上执行此操作,因为脚本仅在主机上运行。

首先使用 docker exec 选择文件,然后使用 docker cp 复制它们是一种选择。 但这是一个 2 步过程。

有人可以帮我一步做到这一点吗?

编辑:

我试过这个。 一步接近,但仍然失败。

# for f in $(docker exec -it SPSRS bash -c "ls /opt/tpa/logs/metrics.csv*");
     do docker cp SPSRS:$f /root/metrices_testing/;
 done


: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-08:45
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-09:00
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-09:15
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-09:30
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-09:45
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-10:00
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-10:15
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-10:30
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-10:45
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-11:00
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-11:15
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-11:30
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-11:45
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-12:00
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-12:15
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-12:30
: no such file or directory lstat /docker/overlay2/193d2ad0d8d087377e3b96cbfb672b0e39132ae5e961872127614c9396f8c068/merged/opt/SPS_18_5_R1/logs/metrics.csv.2018.07.10-12:45

事实上,你的解决方案可以让你的目标只需要一点点改变:

for f in $(docker exec -it SPSRS bash -c "ls /opt/tpa/logs/metrics.csv*"); do docker cp SPSRS:$f /root/metrices_testing/; done

->

for f in $(docker exec -it SPSRS bash -c "ls /opt/tpa/logs/metrics.csv*"); do docker cp SPSRS:`echo $f | sed 's/\r//g'` /root/metrices_testing/; done

这是因为docker exec -it SPSRS bash -c "ls /opt/tpa/logs/metrics.csv*"在每个匹配的字符串中都会有\\r ,所以最终cp找不到容器中的文件。

所以,我们使用echo $f | sed 's/\\r//g' echo $f | sed 's/\\r//g'为每个文件名去掉\\r ,这可以让你工作。

Docker cp 命令支持复制文件夹中的所有内容

docker cp -a container-id:/opt/tpa/logs/  /root/testing/

在上面的示例中,将文件从容器文件夹 /opt/tpa/logs 复制到本地机器 /root/testing/ 文件夹。 这里 /logs/ 中的所有文件都将被复制到本地。 这里的技巧是使用-a选项和docker cp

Docker cp 仍然不支持通配符。 但是,您可以通过以下方式在 Dockerfile 中使用它们:

COPY hom* /mydir/        # adds all files starting with "hom"
COPY hom?.txt /mydir/    # ? is replaced with any single character, e.g., "home.txt"

参考: https : //docs.docker.com/engine/reference/builder/#copy

在容器运行:

dcp() {
  if [ "$#" -eq 1 ]; then
    printf "docker cp %q .\n" "$(hostname):$(readlink -e "$1")"
  else
    local archive="$(mktemp -t "export-XXXXX.tgz")"
    tar czf "$archive" "$@" --checkpoint=.52428800
    printf "docker exec %q cat %q | tar xvz -C .\n" "$(hostname)" "$archive"
  fi
}

然后选择要复制的文件:

dcp /foo/metrics.csv*

它将在容器内创建一个存档并输出一个命令供您运行。 在主机上运行该命令。

例如

docker exec 1c75ed99fa42 cat /tmp/export-x9hg6.tgz | tar xvz -C .

或者,我想你可以在没有临时存档的情况下做到这一点:

dcp() {
  if [ "$#" -eq 1 ]; then
    printf "docker cp %q .\n" "$(hostname):$(readlink -e "$1")"
  else
    printf "docker exec %q tar czC %q" "$(hostname)" "$PWD"
    printf " %q" "$@"
    printf " | tar xzvC .\n"
  fi
}

将为您生成一个命令,例如:

docker exec 1c75ed99fa42 tar czC /root .cache .zcompdump .zinit .zshrc .zshrc.d foo\ bar | tar xzvC .

你甚至不需要别名,这只是一个方便。

docker cp接受文件或 tar 存档,因此您可以将作为参数提供的文件列表打包到 tar 存档, 将存档返回到 stdout并通过管道传输到docker cp

#!/bin/bash

if [[ "$#" -lt 2 || "$1" == "-h" || "$1" == "--help" ]]; then
    printf "Copy files to docker container directory.\n\n"
    echo "Usage: $(basename $0) files... container:directory"
    exit 0
fi

SOURCE="${*%${!#}}"
TARGET="${@:$#}"

tar cf - $SOURCE | docker cp - $TARGET

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM