探索Docker容器的文件系统

use*_*128 561 linux filesystems docker

我注意到docker我需要了解容器内发生的事情或者那里存在的文件.一个例子是从docker索引下载图像 - 你不知道图像包含什么,因此无法启动应用程序.

什么是理想的是能够ssh到他们或等同.有没有一个工具可以做到这一点,或者我认为码头工作者的错误认为我应该能够做到这一点.

Jir*_*iri 656

方法1:快照

您可以通过以下方式评估容器文件系统:

# find ID of your running container:
docker ps

# create image (snapshot) from container filesystem
docker commit 12345678904b5 mysnapshot

# explore this filesystem using bash (for example)
docker run -t -i mysnapshot /bin/bash
Run Code Online (Sandbox Code Playgroud)

这样,您可以在精确的时间内评估正在运行的容器的文件系统.容器仍在运行,不包括将来的更改.

您可以稍后使用(正在运行的容器的文件系统不受影响!)删除快照:

docker rmi mysnapshot
Run Code Online (Sandbox Code Playgroud)

方法2:ssh

如果需要连续访问,可以将sshd安装到容器中并运行sshd守护程序:

 docker run -d -p 22 mysnapshot /usr/sbin/sshd -D

 # you need to find out which port to connect:
 docker ps
Run Code Online (Sandbox Code Playgroud)

这样,您可以使用ssh运行您的应用程序(连接并执行您想要的).

更新 - 方法3:nsenter

使用nsenter,请参阅http://blog.docker.com/2014/06/why-you-dont-need-to-run-sshd-in-docker/

简短版本是:使用nsenter,即使该容器不运行SSH或任何类型的专用守护进程,您也可以将shell放入现有容器中

更新 - 方法4:docker exec

Docker 1.3版(最新版本,您可能需要使用docker apt repo来安装最新版本,截至2014年11月)支持exec与此类似的新命令nsenter.此命令可以在已经运行的容器中运行新进程(容器必须已经运行PID 1进程).您可以运行/bin/bash以探索容器状态:

docker exec -t -i mycontainer /bin/bash
Run Code Online (Sandbox Code Playgroud)

请参阅Docker命令行文档

  • 但请注意,如果您需要访问文件,请使用"docker cp"命令用法:docker cp CONTAINER:PATH HOSTPATH将文件/文件夹从容器文件系统复制到主机路径.路径相对于文件系统的根目录.#> docker cp 7bb0e258aefe:/ etc/debian_version.#> docker cp blue_frog:/ etc/hosts. (6认同)
  • 根据我自己的经验,Docker exec 的限制是该命令必须添加到正在运行的容器上或作为一种入口点。因此,停止的容器超出了此方法的范围。 (5认同)
  • 选项 4 非常重要,应将其移至顶部并重命名为“选项 1”。 (4认同)
  • @JanusTroelsen如果没有shell你可以安装它 - 例如在dockerfile中为alpine linux(它确实没有shell):`RUN apk update && apk add bash`(size:~4MB) (4认同)
  • 要使用 Window 的 linux shell,请使用 `docker exec -t -i mycontainer /bin/sh` (3认同)

Kha*_*oui 226

更新:探索!

此命令可让您探索正在运行的docker容器:

docker exec -it name-of-container bash
Run Code Online (Sandbox Code Playgroud)

在docker-compose中的等价物将是:

docker-compose exec web bash
Run Code Online (Sandbox Code Playgroud)

(在这种情况下,web是服务名称,默认情况下它具有tty.)

一旦你在里面做:

ls -lsa
Run Code Online (Sandbox Code Playgroud)

或任何其他bash命令,如:

cd ..
Run Code Online (Sandbox Code Playgroud)

此命令可让您浏览泊坞窗图像:

docker run --rm -it --entrypoint=/bin/bash name-of-image
Run Code Online (Sandbox Code Playgroud)

一旦进去:

ls -lsa
Run Code Online (Sandbox Code Playgroud)

或任何其他bash命令,如:

cd ..
Run Code Online (Sandbox Code Playgroud)

-it代表互动......和TTY.


此命令可让您检查正在运行的docker容器或映像:

docker inspect name-of-container-or-image

您可能想要这样做,并找出是否有任何bashsh在那里.在json返回中查找entrypoint或cmd.

请参阅docker exec文档

请参阅docker-compose exec文档

请参阅docker检查文档

  • 这非常有用,谢谢!我需要将 docker 映像文件结构中包含的文件拖放到应用程序中,但除非以 GUI 格式打开,否则这是不可能的。知道我该如何解决这个问题吗? (2认同)
  • 显然,这仅适用于已安装bash的容器。 (2认同)
  • 对于正在研究如何在Windows容器/ Powershell上执行此操作的用户,命令为`docker exec -ti <name> powershell`([source](https://forums.docker.com/t/using-powershell-on -主机连接到容器/ 25856/2)) (2认同)

Ily*_*jov 147

您可以将容器的文件系统存档到tar文件中:

docker export adoring_kowalevski > contents.tar
Run Code Online (Sandbox Code Playgroud)

即使您的容器已停止且没有任何shell程序,这种方式仍然有效/bin/bash.我的意思是像Docker文档中的 hello-world图像.

  • 我只是想列出没有安装标准UNIX工具的容器的内容.上面的`export`示例的变体出现了:`docker export adoring_kowalevski | tar tf -` (7认同)
  • 对粗心的警告:这可能导出_lot_数据(> GB)并需要很长时间. (3认同)
  • @berto并不是说这很麻烦,但是您不必在命令末尾使用`f -`,因为tar默认从标准输入中读取。简单地`docker export adoring_kowalevski | 焦油工程。 (3认同)
  • @ShaunBouckaert `tar f` 的默认值取决于一个人的配置。一部分是`TAPE`环境变量。其他人作为构建的一部分进行控制。最终的结果是,永远不要假设它读取 _stdin_ 或写入 _stdout_,而是始终明确声明。 (2认同)

Rov*_*ion 41

容器的文件系统位于docker的数据文件夹中,通常位于/ var/lib/docker中.要启动和检查正在运行的容器文件系统,请执行以下操作:

hash=$(docker run busybox)
cd /var/lib/docker/aufs/mnt/$hash
Run Code Online (Sandbox Code Playgroud)

现在,当前工作目录是容器的根目录.

  • 但这不包括任何已安装的卷. (3认同)

Gau*_*v24 27

在容器创建之前:

如果要探索容器内安装的映像的结构,可以执行此操作

sudo docker image save image_name > image.tar
tar -xvf image.tar
Run Code Online (Sandbox Code Playgroud)

这将使您可以看到图像的所有图层及其在json文件中的配置.

容器创建后:

为此,上面已经有很多答案了.我这样做的首选方式是 -

docker exec -t -i container /bin/bash
Run Code Online (Sandbox Code Playgroud)

  • 这里应该提到的是,只有在与镜像架构相同的机器上运行 bash 时,容器内运行才有效。如果您在 PC 上尝试查看树莓派的图像文件系统,bash 技巧将不起作用。 (4认同)

小智 20

当容器实际启动时,最受欢迎的答案是为我工作,但是当它无法运行时,例如你想要从容器中复制文件时,这已经保存了我:

docker cp <container-name>:<path/inside/container> <path/on/host/>
Run Code Online (Sandbox Code Playgroud)

感谢docker cp(link),您可以直接从容器中复制,因为它是文件系统的任何其他部分.例如,恢复容器内的所有文件:

mkdir /tmp/container_temp
docker cp example_container:/ /tmp/container_temp/
Run Code Online (Sandbox Code Playgroud)

请注意,您不需要指定要递归复制.

  • 为什么这没有更多+ 1!绝对是最好的方式 (5认同)

pie*_*bot 17

在运行Docker 1.3.1的Ubuntu 14.04上,我在以下目录中的主机上找到了容器根文件系统:

/var/lib/docker/devicemapper/mnt/<container id>/rootfs/
Run Code Online (Sandbox Code Playgroud)

完整的Docker版本信息:

Client version: 1.3.1
Client API version: 1.15
Go version (client): go1.3.3
Git commit (client): 4e9bbfa
OS/Arch (client): linux/amd64
Server version: 1.3.1
Server API version: 1.15
Go version (server): go1.3.3
Git commit (server): 4e9bbfa
Run Code Online (Sandbox Code Playgroud)

  • 对于Ubuntu 16.10和docker 1.12.1,遗憾的是不再是这种情况(没有`devicemapper`directory).该文件存在于`/ var/lib/docker/overlay/<a sha256,显然是/<upper或merged>/...`下.我不确定访问那里的文件是多么便携/安全 (2认同)

Gau*_*rma 12

尝试使用

docker exec -it <container-name> /bin/bash
Run Code Online (Sandbox Code Playgroud)

可能有可能没有实现bash.为此你可以使用

docker exec -it <container-name> sh
Run Code Online (Sandbox Code Playgroud)


tel*_*mon 11

我使用的另一个脏技巧是aufs/devicemapper不可知.

我查看容器正在运行的命令,例如docker ps ,如果它是apache,或者java我只是执行以下操作:

sudo -s
cd /proc/$(pgrep java)/root/
Run Code Online (Sandbox Code Playgroud)

并且你在容器里面.

基本上/proc/<PID>/root/,只要该进程由容器运行,您就可以以root用户身份进入文件夹.谨防符号链接使用该模式是没有意义的.


Flo*_*ent 11

除非您的容器不是真正的Linux系统,否则投票最多的答案是好的.

许多容器(尤其是基于go的容器)没有任何标准二进制文件(no /bin/bash/bin/sh).在这种情况下,您需要直接访问实际的容器文件:

奇迹般有效:

name=<name>
dockerId=$(docker inspect -f {{.Id}} $name)
mountId=$(cat /var/lib/docker/image/aufs/layerdb/mounts/$dockerId/mount-id)
cd /var/lib/docker/aufs/mnt/$mountId
Run Code Online (Sandbox Code Playgroud)

注意:您需要以root身份运行它.

  • 我更新了命令以匹配新的 docker 存储结构。 (2认同)
  • 在运行 docker 19.03 的系统上,mountId 现在位于 /var/lib/docker/image/overlay2/$dockerId/mount-id 中,安装的文件系统位于 /var/lib/docker/overlay2/$mountId/merged/ 中或者您只需使用上面@Raphael 的好答案,即使再次更改覆盖文件系统的使用方式,它也应该继续工作。 (2认同)

Adi*_*ana 11

仅适用于 LINUX

我使用的最简单的方法是使用 proc dir,容器必须正在运行才能检查 docker 容器文件。

  1. 找出容器的进程 ID (PID) 并将其存储到某个变量中

    PID=$(docker inspect -f '{{.State.Pid}}' your-container-name-here)

  2. 确保容器进程正在运行,并使用变量名进入容器文件夹

    cd /proc/$PID/root

如果你想通过目录而不找出PID号,只需使用这个长命令

cd /proc/$(docker inspect -f '{{.State.Pid}}' your-container-name-here)/root
Run Code Online (Sandbox Code Playgroud)

提示:

进入容器后,你所做的一切都会影响容器的实际进程,比如停止服务或者改变端口号。

希望能帮助到你

笔记:

此方法仅在容器仍在运行时有效,否则,如果容器已停止或删除,则该目录将不再存在


Rap*_*ael 9

现有的答案都没有解决容器退出(并且无法重新启动)和/或没有安装任何 shell(例如 distroless 的)的情况。只要您有对 Docker 主机的 root 访问权限,这个就可以工作。

对于真正的手动检查,首先找出层 ID:

docker inspect my-container | jq '.[0].GraphDriver.Data'
Run Code Online (Sandbox Code Playgroud)

在输出中,您应该看到类似

"MergedDir": "/var/lib/docker/overlay2/03e8df748fab9526594cfdd0b6cf9f4b5160197e98fe580df0d36f19830308d9/merged"
Run Code Online (Sandbox Code Playgroud)

导航到此文件夹(以 root 身份)以查找容器文件系统的当前可见状态。


小智 8

我想这样做,但我无法执行到我的容器中,因为它已经停止并且由于我的代码中的一些错误而没有再次启动。

对我有用的是将整个容器的内容复制到一个新文件夹中,如下所示:

docker cp container_name:/app/ new_dummy_folder
Run Code Online (Sandbox Code Playgroud)

然后我就可以像浏览普通文件夹一样浏览该文件夹的内容。


小智 6

在较新版本的 Docker 上,您可以运行docker exec [container_name]它在容器内运行 shell

所以要获取容器中所有文件的列表,只需运行 docker exec [container_name] ls


shx*_*shx 6

在我的情况下,除了,容器中没有任何外壳支持sh。所以,这就像一个魅力

docker exec -it <container-name> sh
Run Code Online (Sandbox Code Playgroud)


And*_*ong 5

您可以使用潜水通过TUI交互查看图像内容

https://github.com/wagoodman/dive

在此处输入图片说明


LeY*_*ble 5

这将为图像启动一个 bash 会话:

docker run --rm -it --entrypoint=/bin/bash


小智 5

如果您使用的是 Docker v19.03,请按照以下步骤操作。

# find ID of your running container:

  docker ps

# create image (snapshot) from container filesystem
  
  docker commit 12345678904b5 mysnapshot

# explore this filesystem 
  
  docker run -t -i mysnapshot /bin/sh
Run Code Online (Sandbox Code Playgroud)