【问题标题】:How to copy files from host to Docker container?如何将文件从主机复制到 Docker 容器?
【发布时间】:2014-05-19 09:21:26
【问题描述】:

我正在尝试为我们使用的 Docker 容器构建备份和恢复解决方案。

我有自己创建的 Docker 基础映像 ubuntu:base,并且不想每次都使用 Docker 文件重新构建它来添加文件。

我想创建一个从主机运行的脚本,并使用ubuntu:base Docker 映像创建一个新容器,然后将文件复制到该容器中。

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

【问题讨论】:

  • 如果你不想重建,为什么不 "docker commit" 呢?这样可以保存您的图像。
  • 只是对没有人提出的一个概念的评论:通常,将容器视为“短暂的”。有一些用例可以将文件复制到/从正在运行的容器中(测试、原型设计)。但是,如果您发现自己无法使用 Dockerfiles 和/或 compose 重建所需的内容,那么您可能处于一个糟糕的位置。您通常不希望将容器作为操作系统甚至虚拟机对象来备份。一般来说:-)
  • @BerenddeBoer 的链接现已过时,这是新的 URL:docs.docker.com/engine/reference/commandline/commit

标签: docker docker-container


【解决方案1】:

cp 命令可用于复制文件。

可以将一个特定文件复制到容器中,例如:

docker cp foo.txt container_id:/foo.txt

可以从容器中复制一个特定文件,例如:

docker cp container_id:/foo.txt foo.txt

为了强调,container_id容器 ID,不是 图像 ID。 (使用docker ps 查看包含container_ids 的列表。)

文件夹src 包含的多个文件可以使用以下命令复制到target 文件夹中:

docker cp src/. container_id:/target
docker cp container_id:/src/. target

参考:Docker CLI docs for cp

在 1.8 之前的 Docker 版本中,只能将文件从容器复制到主机。不是从主机到容器。

【讨论】:

  • 另请注意,这可以在主机 vm 或主操作系统上,并且可以在主机到容器或 vm 到主机(或主操作系统)上工作
  • 在 Dockerfile 中,您可以使用 ADD 关键字在构建期间添加文件。
  • @h3nrik COPY preferred over ADD 如果适用。
  • 使用docker cp从容器复制到主机效果很好,但是当使用它从主机复制文件到容器时,没有效果......有人知道为什么吗? docker 版本:Docker 版本 1.10.3,构建 cb079f6-unsupported
  • 我可以使用 docker cp 将多个文件从主机复制到容器吗?
【解决方案2】:
  1. 获取容器名称或短容器ID:

    $ docker ps
    
  2. 获取完整的容器 ID:

    $ docker inspect -f   '{{.Id}}'  SHORT_CONTAINER_ID-or-CONTAINER_NAME
    
  3. 复制文件:

    $ sudo cp path-file-host /var/lib/docker/aufs/mnt/FULL_CONTAINER_ID/PATH-NEW-FILE
    

示例:

$ docker ps

CONTAINER ID      IMAGE    COMMAND       CREATED      STATUS       PORTS        NAMES

d8e703d7e303   solidleon/ssh:latest      /usr/sbin/sshd -D                      cranky_pare

$ docker inspect -f   '{{.Id}}' cranky_pare

$ docker inspect -f   '{{.Id}}' d8e703d7e303

d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5

$ sudo cp file.txt /var/lib/docker/aufs/mnt/**d8e703d7e3039a6df6d01bd7fb58d1882e592a85059eb16c4b83cf91847f88e5**/root/file.txt

【讨论】:

  • 对我来说,主机的安装路径不包含aufs,而是devicemapper。检查容器安装路径(在运行时)的最简单方法是运行命令mount
  • 我尝试了上述解决方案。它将文件复制到 docker 特定目录中。但是,当我将 bash 用于 docker 容器时,文件不会出现在那里。有什么我想念的吗?
  • 新路径是/var/lib/docker/devicemapper/mnt/>/rootfs/
  • 对我来说,在 Docker 1.4.1(当前最新)上,它是 /var/lib/docker/aufs/diff/<id>/
  • 对于可怜的 MacOS 用户怎么办?对我来说,挂载目录在/var/lib 中。 find / -name docker 也没有帮助。
【解决方案3】:

最干净的方法是在启动容器时在容器上挂载一个主机目录:

{host} docker run -v /path/to/hostdir:/mnt --name my_container my_image
{host} docker exec -it my_container bash
{container} cp /mnt/sourcefile /path/to/destfile

【讨论】:

  • 如何运行容器?我以为你只能用一张图片来做到这一点。
  • 当容器存在时我无法让它工作,也就是之前运行过。下面的焦油效果很好。
  • 这对我有用的唯一方法是在运行映像的同时附加卷(实例化容器)。结束于:docker run -d -p -v /host/path:/mnt --name container_name image_name
  • 这对我不起作用。至少不能运行容器。只能运行图像
  • 我很惊讶docker cp 是单向操作!
【解决方案4】:

以下是一种相当丑陋的做法,但它确实有效。

docker run -i ubuntu /bin/bash -c 'cat > file' < file

【讨论】:

  • 这很好用!但不要忘记提交更改:docker commit `docker ps -l -q` ubuntu-with-file。否则更改将丢失(使用您想要的任何名称,而不是 ubuntu-with-file
  • 此外,我们可以使用新的docker exec 功能来处理正在运行的容器:docker exec -it &lt;container_id&gt; bash -c 'cat &gt; /path/to/container/file' &lt; /path/to/host/file/
  • @Mikl 我认为应该是docker exec -i ... 而不是-it,因为从文件输入时没有 TTY。
  • 如果你仍然停留在旧版本的 Docker 上(和我一样)并且想要复制整个目录,你可以这样做:tar -c -v -f - /path/to/host/directory | docker exec -i &lt;container-name&gt; bash -c 'tar -x -v --strip-components 1 -f - -C /path/to/container/directory'
  • 嗯,这不适用于 Docker 19.03.8、主机 Centos 8、ubuntu:18.04 映像。它确实在容器上创建了file,但它是空白的。
【解决方案5】:

通常有三种类型:

  1. 从容器到主机

    docker cp container_id:./bar/foo.txt .
    

  1. 从主机到容器

    docker exec -i container_id sh -c 'cat > ./bar/foo.txt' < ./foo.txt
    
  2. 从主机复制到容器的第二种方法:

    docker cp foo.txt mycontainer:/foo.txt
    

  1. 从一个容器到一个容器混合1和2

    docker cp container_id1:./bar/foo.txt .
    
    docker exec -i container_id2 sh -c 'cat > ./bar/foo.txt' < ./foo.txt
    

【讨论】:

  • docker cp 双向工作。无需执行、cat 和重定向。 docker cp host_file.txt 容器:/path/
  • 如果需要复制多个文件,tar 非常方便,如下所示:tar -czvf tmp.tar.gz *.* &amp;&amp; docker exec -i container_id2 sh -c 'cat &gt; ./bar/tmp.tar.gz &amp;&amp; tar -xzvf tmp.tar.gz' &lt; ./tmp.tar.gz
【解决方案6】:

如果您需要在正在运行的容器上执行此操作,您可以使用 docker exec(在 1.3 中添加)。

首先,找到容器的名称或 ID:

$ docker ps
CONTAINER ID        IMAGE                        COMMAND             CREATED             STATUS              PORTS                   NAMES
b9b7400ddd8f        ubuntu:latest                "/bin/bash"         2 seconds ago       Up 2 seconds                                elated_hodgkin

在上面的示例中,我们可以使用b9b7400ddd8felated_hodgkin

如果您想将主机上/tmp/somefiles中的所有内容复制到容器中的/var/www

$ cd /tmp/somefiles
$ tar -cv * | docker exec -i elated_hodgkin tar x -C /var/www

然后我们可以在容器中执行/bin/bash 并验证它是否有效:

$ docker exec -it elated_hodgkin /bin/bash
root@b9b7400ddd8f:/# ls /var/www
file1  file2

【讨论】:

  • 在 Centos 7.4 上的 docker 1.16 上运行良好 伟大的创新理念。
【解决方案7】:
  1. 创建一个新的 dockerfile 并使用现有的图像作为您的基础。

    FROM myName/myImage:latest
    
    ADD myFile.py bin/myFile.py
    
  2. 然后构建容器:

    docker build .
    

【讨论】:

  • 这对我有用。没有其他的。谢谢!
  • 它将创建一个新图像,而不是直接创建一个新容器。如果您在 myFile.py 更改时重用此图像,它将使用该文件的旧版本,除非您重建该图像。
  • 只有在远程服务器上进行测试时,我才发现这是最快的方法。
  • 根据this,大多数人应该使用 COPY 而不是 ADD。但是对于本地文件(如本例),它们是等价的。
【解决方案8】:

解决方法如下,

从 Docker 外壳,

root@123abc:/root#  <-- get the container ID

来自主机

cp thefile.txt /var/lib/docker/devicemapper/mnt/123abc<bunch-o-hex>/rootfs/root

文件应直接复制到文件系统上容器所在的位置。

【讨论】:

  • 很好的答案。在较新的 docker 版本中,路径已重命名为 /var/lib/docker/aufs/mnt/
  • devicemapper 路径似乎不适用于 docker 1.6 的 Fedora。已将其作为单独的 Q,stackoverflow.com/questions/29939419/…,任何 cmets 将不胜感激。
  • 文件/var/lib/docker不存在....
【解决方案9】:

将文件复制到正在运行的容器中的另一种解决方案是使用 tar:

tar -c foo.sh | docker exec -i theDockerContainer /bin/tar -C /tmp -x

将文件foo.sh复制到容器的/tmp中。

编辑:删除冗余-f,感谢Maartens 评论。

【讨论】:

  • 如果您需要发送整个目录,这很好。对于单个文件,Erik 的回答比较简单。
  • @Kelvin:但是 tar 也保留了文件属性和名称。除此之外,这意味着您只需键入一次名称(然后您就可以从 shell 中获得制表符完成)。所以我想说tar其实更简单,只要装在容器里就行了。
  • -f - 虽然有点多余,但默认行为是无论如何都要写入标准输出。
  • 这意味着存在对 tar 的主机依赖
  • 你是对的 - 你需要在主机和容器内安装 tar。现在使用 docker cp 是更好的解决方案。
【解决方案10】:

将文件从主机复制到正在运行的容器

docker exec -i $CONTAINER /bin/bash -c "cat > $CONTAINER_PATH" < $HOST_PATH

基于 Erik's answer 以及 Mikl 和 z0r 的 cmets。

【讨论】:

  • 在传输到正在运行的容器时,公认的解决方案有时会干扰文件的缩进。这非常适合这种情况
【解决方案11】:

这是对标题中这个问题中提出的“将文件从主机复制到 Docker 容器”问题的直接回答。

试试docker cp。这是最简单的方法,甚至可以在我的 Mac 上使用。用法:

docker cp /root/some-file.txt some-docker-container:/root

这会将您主机上目录/root 中的文件some-file.txt 复制到名为some-docker-container 的Docker 容器中,并复制到目录/root 中。它非常接近安全复制语法。如上一篇文章所示,您可以反之亦然。即,您还可以将文件从容器复制到主机。

在你下载这篇文章之前,请输入docker cp --help。阅读文档可能会很有帮助,有时...

如果您不喜欢这种方式,并且希望在您已创建并正在运行的容器中存储数据量,那么今天您的唯一选择就是重新创建。另请参阅How can I add a volume to an existing Docker container?

【讨论】:

    【解决方案12】:

    我在这里尝试了大多数(赞成的)解决方案,但在 docker 17.09(2018 年)中不再有 /var/lib/docker/aufs 文件夹。

    这个简单的docker cp 解决了这个任务。

    docker cp c:\path\to\local\file container_name:/path/to/target/dir/
    

    如何获取容器名称?

     docker ps 
    

    有一个NAMES 部分。不要使用IMAGE

    【讨论】:

      【解决方案13】:

      使用 Docker 1.8,docker cp 能够将文件从主机复制到容器。请参阅 Docker 博客文章Announcing Docker 1.8: Content Trust, Toolbox, and Updates to Registry and Orchestration

      【讨论】:

      • 这里是一个例子docker cp foo.txt mycontainer:/foo.txt
      【解决方案14】:

      要在容器和本地文件系统之间复制文件/文件夹,请输入命令:

      docker cp {SOURCE_FILE} {DESTINATION_CONTAINER_ID}:/{DESTINATION_PATH}
      

      例如,

      docker cp /home/foo container-id:/home/dir
      

      要获取容器 ID,请输入给定的命令:

      docker ps
      

      以上内容摘自docker.com

      【讨论】:

        【解决方案15】:

        假设容器已经在运行,输入给定的命令:

        # cat /path/to/host/file/ | docker exec -i -t <container_id> bash -c "/bin/cat > /path/to/container/file"
        

        要使用共享目录共享文件,请键入给定命令运行容器:

        # docker run -v /path/to/host/dir:/path/to/container/dir ...
        

        注意:由于容器的用户与主机的用户不同,因此可能会出现权限问题。

        【讨论】:

        • 另外:docker exec -it &lt;container_id&gt; bash -c 'cat &gt; /path/to/container/file' &lt; /path/to/host/file/
        • 注意cat一旦退出就不会被终止。如果这对您很重要(如果您正在复制 bash 脚本,bash 将拒绝运行它们),您应该运行 lsof | grep yourfilename 并终止保存所述文件的 cat 进程。
        • 谢谢!很棒的小费。你能告诉我如何用一个命令杀死这个进程吗?像kill $(lsof | grep /path/to/file | sed ...) 这样的东西。我会很感激你的帮助
        • kill $(docker top CONTAINERNAME | sed -n '/cat$/p' | sed 's/^root[^0-9]\+\([0-9]\+\).*$/\1/')
        【解决方案16】:

        这是将数据从 Docker 复制到主机的命令:

        docker cp container_id:file path/filename /hostpath
        
        docker cp a13fb9c9e674:/tmp/dgController.log /tmp/
        

        下面是从主机复制数据到docker的命令:

        docker cp a.txt ccfbeb35116b:/home/
        

        【讨论】:

          【解决方案17】:

          在docker环境下,所有容器都在目录下:

          /var/lib/docker/aufs/required-docker-id/

          要将源目录/文件复制到容器的任何部分,请键入给定的命令:

          sudo cp -r mydir/ /var/lib/docker/aufs/mnt/required-docker-id/mnt/

          【讨论】:

            【解决方案18】:

            Docker cp 命令是一个方便的实用程序,允许在容器和主机系统之间复制文件和文件夹。

            如果要将文件从主机系统复制到容器,则应使用 docker cp 命令,如下所示:

            docker cp host_source_path container:destination_path
            

            首先使用 docker ps 命令列出正在运行的容器:

            abhishek@linuxhandbook:~$ sudo docker ps
            CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              
              PORTS               NAMES
              8353c6f43fba        775349758637        "bash"              8 seconds ago       Up 7 
              seconds                            ubu_container
            

            您需要知道容器 ID 或容器名称。在我的例子中,docker 容器名称是 ubu_container。容器 ID 为 8353c6f43fba。

            如果你想验证文件是否复制成功,你可以通过以下方式进入你的容器,然后使用常规的Linux命令:

            docker exec -it ubu_container bash
            

            将文件从主机系统复制到 docker 容器 使用 docker cp 进行复制类似于 Linux 中的复制命令。

            我将复制一个名为 a.py 的文件到容器中的 home/dir1 目录。

            docker cp a.py ubu_container:/home/dir1
            

            如果文件被成功复制,您将不会在屏幕上看到任何输出。如果目标路径不存在,您会看到错误:

            abhishek@linuxhandbook:~$ sudo docker cp a.txt ubu_container:/home/dir2/subsub
                    Error: No such container:path: ubu_container:/home/dir2
            

            如果目标文件已经存在,它将被覆盖而没有任何警告。

            您也可以使用容器 ID 代替容器名称:

            docker cp a.py 8353c6f43fba:/home/dir1
            

            【讨论】:

              【解决方案19】:

              如果主机是CentOS或Fedora,有一个代理不在/var/lib/docker/aufs下,但在/proc下:

              cp -r /home/user/mydata/* /proc/$(docker inspect --format "{{.State.Pid}}" <containerid>)/root
              

              此 cmd 会将data 目录的所有内容复制到 ID 为“containerid”的容器的/

              【讨论】:

              • 这不是 Redhat 独有的:它也适用于 Debian。 (也许所有带有/proc 的 Gnu/Linux)。还要扩展路径以将文件放在其他地方,而不仅仅是根目录。
              【解决方案20】:

              tardocker cp 是复制目录中所有内容的好组合。

              创建数据卷容器

              docker create --name dvc --volume /path/on/container cirros
              

              保留目录层次结构

              tar -c -C /path/on/local/machine . | docker cp - dvc:/path/on/container
              

              检查你的工作

              docker run --rm --volumes-from dvc cirros ls -al /path/on/container
              

              【讨论】:

                【解决方案21】:

                您可以使用跟踪本地计算机的 IP 地址

                ifconfig
                

                然后进入你的 Docker 容器并输入

                scp user_name@ip_address:/path_to_the_file destination
                

                无论如何,如果您没有安装 SSH 客户端和服务器,只需使用以下方式安装它:

                sudo apt-get install openssh-server
                

                【讨论】:

                • 非常感谢,它对我来说效果很好。另外,我发现它比其他方式更有效
                • 在安全性方面这是一个糟糕的解决方案。
                【解决方案22】:

                如果像我这样的人不清楚@h3nrik 答案中的mycontainer 是什么意思,它实际上是容器ID。要将 /app/example_scenes/1440p60 中的文件 WarpSquare.mp4 从退出的 docker 容器复制到当前文件夹,我使用了这个。

                docker cp `docker ps -q -l`:/app/example_scenes/1440p60/WarpSquare.mp4 .
                

                docker ps -q -l 提取最后一个退出实例的容器 ID。如果它不是已退出的容器,您可以通过docker container lsdocker ps 获取它

                【讨论】:

                • 您可以使用docker ps -adocker container ls -a 列出已退出容器的ID。
                【解决方案23】:
                docker cp SRC_PATH CONTAINER_ID:DEST_PATH
                

                例如,我想将我的文件 xxxx/download/jenkins 复制到 tomcat

                我开始获取容器Tomcat的id

                docker ps
                
                CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
                63686740b488        tomcat              "catalina.sh run"   12 seconds ago      Up 11 seconds       0.0.0.0:8080->8080/tcp   peaceful_babbage
                
                docker cp xxxx/download/jenkins.war  63686740b488:usr/local/tomcat/webapps/
                

                【讨论】:

                  【解决方案24】:

                  容器向上语法:

                  docker run -v /HOST/folder:/Container/floder 
                  

                  在 docker 文件中

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

                  【讨论】:

                    【解决方案25】:

                    许多发现这个问题的人实际上可能会遇到将文件复制到 Docker 映像的问题在创建 Docker 映像时(我做过)。

                    在这种情况下,您可以在用于创建图像的Dockerfile 中使用COPY 命令。

                    See the documentation.

                    【讨论】:

                      【解决方案26】:

                      这是一个在运行 tomcat 容器时复制单个文件的在线工具。

                      docker run -v /PATH_TO_WAR/sample.war:/usr/local/tomcat/webapps/myapp.war -it -p 8080:8080 tomcat
                      

                      这会将war文件复制到webapps目录并立即让您的应用运行。

                      【讨论】:

                      • -v 将挂载(即创建链接),而不是复制
                      • 结果的不同在于挂载隐藏了之前的容器内容,例如如果您在容器文件夹上安装主机文件夹,您将无法再看到以前的容器文件夹内容
                      【解决方案27】:
                      docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
                      

                      目标路径必须是预先存在的

                      【讨论】:

                        【解决方案28】:

                        我最喜欢的方法:

                        容器:

                        CONTAINER_ID=$(docker ps | grep <string> | awk '{ print $1 }' | xargs docker inspect -f '{{.Id}}')
                        

                        文件.txt

                        mv -f file.txt /var/lib/docker/devicemapper/mnt/$CONTAINER_ID/rootfs/root/file.txt
                        

                        mv -f file.txt /var/lib/docker/aufs/mnt/$CONTAINER_ID/rootfs/root/file.txt
                        

                        【讨论】:

                        【解决方案29】:

                        我找到的将文件复制到容器的最佳方法是使用 docker run 命令的-v 选项在主机上挂载一个目录。

                        【讨论】:

                          【解决方案30】:

                          有很好的答案,但太具体了。我发现docker ps 是获取您感兴趣的容器 ID 的好方法。然后做

                          mount | grep <id>
                          

                          查看卷的安装位置。那是

                          /var/lib/docker/devicemapper/mnt/<id>/rootfs/
                          

                          对我来说,但它可能是不同的路径,具体取决于操作系统和配置。现在只需将文件复制到该路径即可。

                          使用-v 并不总是可行的。

                          【讨论】:

                            猜你喜欢
                            • 2014-03-29
                            • 1970-01-01
                            • 2015-07-08
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多