我正在尝试为我们使用的 Docker 容器构建备份和恢复解决方案。
我有我创建的 Docker 基础映像 ubuntu:base
,并且不希望每次都使用 Docker 文件重新构建它以向其中添加文件。
我想创建一个从主机运行的脚本,并使用 ubuntu:base
Docker 映像创建一个新容器,然后将文件复制到该容器中。
如何将文件从主机复制到容器?
cp
命令可用于复制文件。
可以将一个特定文件复制到容器中,例如:
docker cp foo.txt container_id:/foo.txt
可以从容器中复制一个特定文件,例如:
docker cp container_id:/foo.txt foo.txt
为了强调,container_id
是 容器 ID,不是 图像 ID。 (使用 docker ps
查看包含 container_id
的列表。)
可以使用以下方法将文件夹 src
包含的多个文件复制到 target
文件夹中:
docker cp src/. container_id:/target
docker cp container_id:/src/. target
在 1.8 之前的 Docker 版本中,只能将文件从容器复制到主机。不是从主机到容器。
获取容器名称或短容器 id:$ docker ps 获取完整容器 id:$ docker inspect -f '{{.Id}}' SHORT_CONTAINER_ID-or-CONTAINER_NAME 复制文件:$ sudo cp path-file-host /var/lib/码头工人/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
。
/var/lib/docker/aufs/diff/<id>/
/var/lib
中。 find / -name docker
也没有帮助。
最干净的方法是在启动容器时在容器上挂载一个主机目录:
{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
是一种单向操作!
以下是一种相当丑陋的方法,但它有效。
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 <container_id> bash -c 'cat > /path/to/container/file' < /path/to/host/file/
docker exec -i ...
而不是 -it
,因为从文件输入时没有 TTY。
tar -c -v -f - /path/to/host/directory | docker exec -i <container-name> bash -c 'tar -x -v --strip-components 1 -f - -C /path/to/container/directory'
file
,但它是空白的。
通常有以下三种类型:
从容器到主机 docker cp container_id:./bar/foo.txt 。
docker cp 命令也可以双向工作。
https://i.stack.imgur.com/qnhSi.jpg
从主机到容器 docker exec -i container_id sh -c 'cat > ./bar/foo.txt' < ./foo.txt 从主机复制到容器的第二种方法:docker cp foo.txt mycontainer:/foo。文本
https://i.stack.imgur.com/5GaiK.jpg
从容器到容器混合 1 和 2 docker cp container_id1:./bar/foo.txt 。 docker exec -i container_id2 sh -c 'cat > ./bar/foo.txt' < ./foo.txt
https://i.stack.imgur.com/pGr45.jpg
tar -czvf tmp.tar.gz *.* && docker exec -i container_id2 sh -c 'cat > ./bar/tmp.tar.gz && tar -xzvf tmp.tar.gz' < ./tmp.tar.gz
如果您需要在正在运行的容器上执行此操作,您可以使用 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
在上面的示例中,我们可以使用 b9b7400ddd8f
或 elated_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
创建一个新的 dockerfile 并使用现有的图像作为您的基础。 FROM myName/myImage:latest ADD myFile.py bin/myFile.py 然后构建容器: docker build 。
解决方案如下,
从 Docker 外壳,
root@123abc:/root# <-- get the container ID
来自主持人
cp thefile.txt /var/lib/docker/devicemapper/mnt/123abc<bunch-o-hex>/rootfs/root
该文件应直接复制到容器位于文件系统上的位置。
/var/lib/docker
不存在....
将文件复制到正在运行的容器中的另一种解决方案是使用 tar:
tar -c foo.sh | docker exec -i theDockerContainer /bin/tar -C /tmp -x
将文件 foo.sh
复制到容器的 /tmp
中。
编辑:删除冗余 -f
,感谢 Maarten 的评论。
-f -
虽然有点多余,但默认行为是无论如何都要写入标准输出。
将文件从主机复制到正在运行的容器
docker exec -i $CONTAINER /bin/bash -c "cat > $CONTAINER_PATH" < $HOST_PATH
基于 Erik's answer 以及 Mikl 和 z0r 的评论。
这是对标题中这个问题中提出的“将文件从主机复制到 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?。
我在这里尝试了大多数(赞成的)解决方案,但在 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
。
在 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
要在容器和本地文件系统之间复制文件/文件夹,请键入命令:
docker cp {SOURCE_FILE} {DESTINATION_CONTAINER_ID}:/{DESTINATION_PATH}
例如,
docker cp /home/foo container-id:/home/dir
要获取 contianer id,请键入给定的命令:
docker ps
以上内容取自docker.com。
假设容器已经在运行,输入给定的命令:
# 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 <container_id> bash -c 'cat > /path/to/container/file' < /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/')
这是将数据从 Docker 复制到主机的命令:
docker cp container_id:file path/filename /hostpath
docker cp a13fb9c9e674:/tmp/dgController.log /tmp/
以下是将数据从主机复制到 docker 的命令:
docker cp a.txt ccfbeb35116b:/home/
在 docker 环境中,所有容器都在目录中:
/var/lib/docker/aufs/required-docker-id/
要将源目录/文件复制到容器的任何部分,请键入给定的命令:
sudo cp -r mydir/ /var/lib/docker/aufs/mnt/required-docker-id/mnt/
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
容器向上语法:
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"
如果主机是 CentOS 或 Fedora,则在 /var/lib/docker/aufs
中没有代理,但在 /proc
下:
cp -r /home/user/mydata/* /proc/$(docker inspect --format "{{.State.Pid}}" <containerid>)/root
此 cmd 会将 data
目录的所有内容复制到 ID 为“containerid”的容器的 /
。
/proc
的 Gnu/Linux)。还要扩展路径以将文件放在其他地方,而不仅仅是根目录。
tar
和 docker 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
如果像我这样的人不清楚@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 ls
或 docker ps
获取它
docker ps -a
或 docker container ls -a
列出已退出容器的 ID。
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/
docker cp [OPTIONS] SRC_PATH CONTAINER:DEST_PATH
目标路径必须预先存在
许多发现这个问题的人实际上可能在创建 Docker 映像时遇到了将文件复制到它的问题(我做过)。
在这种情况下,您可以使用 Dockerfile
中的 COPY
命令来创建图像。
这是一个用于在运行 tomcat 容器时复制单个文件的在线工具。
docker run -v /PATH_TO_WAR/sample.war:/usr/local/tomcat/webapps/myapp.war -it -p 8080:8080 tomcat
这会将战争文件复制到 webapps 目录并立即让您的应用程序运行。
我最喜欢的方法:
容器:
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
将文件复制到我发现的容器的最佳方法是使用 docker run 命令的 -v
选项在主机上安装目录。
有很好的答案,但太具体了。我发现 docker ps
是获取您感兴趣的容器 ID 的好方法。然后执行
mount | grep <id>
查看卷的安装位置。那是
/var/lib/docker/devicemapper/mnt/<id>/rootfs/
对我来说,但它可能是不同的路径,具体取决于操作系统和配置。现在只需将文件复制到该路径。
使用 -v
并不总是可行的。
我刚开始使用 docker 编译 VLC,以下是从容器中来回复制文件的方法:
su -
cd /var/lib/docker
ls -palR > /home/user/dockerfilelist.txt
在该 txt 中搜索一个熟悉的文件,您将拥有该文件夹,以 root 身份 cd 到它,瞧!复制所有你想要的。
可能有一条带有“合并”的路径,我猜你想要一条带有“差异”的路径。
此外,如果您退出容器并想回到您离开的地方:
docker ps -a
docker start -i containerid
我想当你没有用类似的命令命名任何东西时这很有用
docker run -it registry.videolan.org:5000/vlc-debian-win64 /bin/bash
当然是黑客方法,但那又怎样!
COPY
preferred overADD
适用时。docker cp
从容器复制到主机效果很好,但是当使用它将文件从主机复制到容器时,没有效果......有人知道为什么吗? docker 版本:Docker 版本 1.10.3,构建 cb079f6-unsupported