探索 Docker 容器的文件系统
- 2024-10-09 09:10:00
- admin 原创
- 80
问题描述:
我注意到,在使用 docker 时,我需要了解容器内部发生了什么或容器中存在哪些文件。一个例子是从 docker 索引下载镜像 - 你不知道镜像包含什么,因此无法启动应用程序。
最理想的是能够通过 ssh 进入它们或类似的东西。有没有工具可以做到这一点,或者我对 docker 的概念理解是错误的,认为我应该能够做到这一点。
解决方案 1:
这里有几种不同的方法...
A)使用 docker exec (最简单)
exec
Docker 1.3 或更新版本支持类似于的命令nsenter
。此命令可以在已经运行的容器中运行新进程(容器必须有 PID 1 进程已经在运行)。您可以运行/bin/bash
来探索容器状态:
docker exec -t -i mycontainer /bin/bash
请参阅Docker 命令行文档
B)使用快照
您可以通过以下方式评估容器文件系统:
# 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
这样,您就可以在精确的时间点评估正在运行的容器的文件系统。容器仍在运行,不包括任何未来的更改。
您可以稍后使用以下命令删除快照(正在运行的容器的文件系统不受影响!):
docker rmi mysnapshot
C)使用 ssh
如果需要持续访问,可以将 sshd 安装到容器中并运行 sshd 守护程序:
docker run -d -p 22 mysnapshot /usr/sbin/sshd -D
# you need to find out which port to connect:
docker ps
这样,您就可以使用 ssh 运行您的应用程序(连接并执行您想要的操作)。
D)使用 nsenter
使用nsenter
,请参阅为什么你不需要在 Docker 容器中运行 SSHd
简而言之:使用 nsenter,你可以进入现有容器的 shell,即使该容器没有运行 SSH 或任何类型的专用守护进程
解决方案 2:
更新:探索中!
此命令可以让你探索正在运行的 docker 容器:
docker exec -it name-of-container bash
在 docker-compose 中与之等效的是:
docker-compose exec web bash
(在这种情况下,web 是服务名称,默认情况下它具有 tty。)
进入后执行以下操作:
ls -lsa
或任何其他 bash 命令,例如:
cd ..
此命令可以让你探索docker镜像:
docker run --rm -it --entrypoint=/bin/bash name-of-image
一旦进入:
ls -lsa
或任何其他 bash 命令,例如:
cd ..
代表-it
交互式...和tty。
此命令可以让你检查正在运行的 docker 容器或镜像:
docker inspect name-of-container-or-image
您可能想要这样做并找出其中是否有任何bash
或sh
。在 json 返回中查找 entrypoint 或 cmd。
注意:这个答案依赖于常用工具的存在,但如果没有bash
shell 或常用工具,ls
您可以先在层中添加一个,如果您有权访问Dockerfile
:例如 alpine:
RUN apk add --no-cache bash
否则,如果您无权访问Dockerfile
,则只需将文件从新创建的容器中复制出来,然后通过执行以下操作来查看它们:
docker create <image> # returns container ID the container is never started.
docker cp <container ID>:<source_path> <destination_path>
docker rm <container ID>
cd <destination_path> && ls -lsah
参见docker exec 文档
请参阅docker-compose exec 文档
请参阅docker inspect 文档
请参阅docker create 文档
解决方案 3:
如果您的容器已停止或者没有 shell(例如安装指南hello-world
中提到的,或没有),这可能是探索文件系统的唯一可能方法。alpine
traefik
您可以将容器的文件系统存档到 tar 文件中:
docker export adoring_kowalevski > contents.tar
或者列出文件:
docker export adoring_kowalevski | tar t
请注意,根据图像的不同,这可能需要一些时间和磁盘空间。
解决方案 4:
当容器实际启动时,最受欢迎的答案对我来说是有效的,但是当无法运行并且例如你想要从容器中复制文件时,这之前已经拯救了我:
docker cp <container-name>:<path/inside/container> <path/on/host/>
借助 docker cp ( link ),您可以直接从容器中复制,就像复制文件系统的任何其他部分一样。例如,恢复容器内的所有文件:
mkdir /tmp/container_temp
docker cp example_container:/ /tmp/container_temp/
请注意,您不需要指定想要递归复制。
解决方案 5:
创建容器之前:
如果你想探索容器内安装的图像的结构,你可以这样做
sudo docker image save image_name > image.tar
tar -xvf image.tar
这将使您能够看到 json 文件中存在的图像的所有层及其配置。
容器创建后:
对此,上面已经有很多答案。我更喜欢的方法是 -
docker exec -t -i container /bin/bash
解决方案 6:
您可以使用 dive 与 TUI 交互查看图像内容
https://github.com/wagoodman/dive
解决方案 7:
容器的文件系统位于 docker 的数据文件夹中,通常位于 /var/lib/docker。要启动和检查正在运行的容器文件系统,请执行以下操作:
hash=$(docker run busybox)
cd /var/lib/docker/aufs/mnt/$hash
现在当前工作目录就是容器的根目录。
解决方案 8:
仅适用于 LINUX
我使用的最简单的方法是使用 proc dir,容器必须正在运行才能检查 docker 容器文件。
找出容器的进程 ID (PID) 并将其存储到某个变量中
PID=$(docker inspect -f'{{.State.Pid}}' 你的容器名称在这里)
确保容器进程正在运行,并使用变量名进入容器文件夹
cd /proc/$PID/root
如果你想通过目录而不找出PID号,只需使用这个长命令
cd /proc/$(docker inspect -f '{{.State.Pid}}' your-container-name-here)/root
尖端:
当你进入容器内部之后,你所做的一切都会影响容器的实际进程,比如停止服务或者改变端口号。
希望有帮助。
笔记:
此方法仅当容器仍在运行时才有效,否则,如果容器已停止或删除,该目录将不再存在。
解决方案 9:
尝试使用
docker exec -it <container-name> /bin/bash
有可能 bash 没有实现。为此你可以使用
docker exec -it <container-name> sh
解决方案 10:
在我的例子中,容器中不支持任何 shell,除了sh
。所以,这很有效
docker exec -it <container-name> sh
解决方案 11:
在运行Docker 1.3.1 的Ubuntu 14.04上,我在主机上的以下目录中找到了容器根文件系统:
/var/lib/docker/devicemapper/mnt/<container id>/rootfs/
完整的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
解决方案 12:
除非您的容器不是实际的 Linux 系统,否则得票最多的答案是好的。
许多容器(特别是基于 go 的容器)没有任何标准二进制文件(没有/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
注意:您需要以 root 身份运行它。
解决方案 13:
我使用了另一个与 aufs/devicemapper 无关的肮脏伎俩。
我查看容器正在运行的命令,例如docker ps
,如果它是 apache,或者java
我仅执行以下操作:
sudo -s
cd /proc/$(pgrep java)/root/
现在你已经进入容器内部了。
/proc/<PID>/root/
基本上,只要该进程由容器运行,您就可以以 root 身份 cd 进入文件夹。请注意,使用该模式时,符号链接将毫无意义。
解决方案 14:
现有的答案都没有解决容器退出(并且无法重新启动)和/或没有安装任何 shell(例如无发行版的 shell)的情况。只要您拥有 Docker 主机的 root 访问权限,此方法就可以使用。
对于真正的人工检查,首先找出层 ID:
docker inspect my-container | jq '.[0].GraphDriver.Data'
在输出中,你应该看到类似
"MergedDir": "/var/lib/docker/overlay2/03e8df748fab9526594cfdd0b6cf9f4b5160197e98fe580df0d36f19830308d9/merged"
导航到此文件夹(以 root 身份)以查找容器文件系统的当前可见状态。
解决方案 15:
我想这样做,但是我无法执行到我的容器中,因为它已经停止并且由于我的代码中的某些错误而无法重新启动。
对我有用的是将整个容器的内容简单地复制到一个新文件夹中,如下所示:
docker cp container_name:/app/ new_dummy_folder
然后我就可以像浏览普通文件夹一样浏览该文件夹的内容。
解决方案 16:
这将为图像启动一个 bash 会话:
docker run --rm -it --entrypoint=/bin/bash <image_name>
解决方案 17:
在较新版本的 Docker 中,你可以运行docker exec [container_name]
在容器内运行 shell
因此,要获取容器中所有文件的列表,只需运行docker exec [container_name] ls
解决方案 18:
如果您使用的是 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
解决方案 19:
对我来说,这个效果很好(感谢最后一条评论指出目录/var/lib/docker/):
chroot /var/lib/docker/containers/2465790aa2c4*/root/
这里,2465790aa2c4是正在运行的容器的短 ID(由docker ps显示),后面跟着一个星号。
解决方案 20:
这个答案将帮助那些(像我自己)想要探索docker卷文件系统的人,即使容器没有运行。
列出正在运行的 Docker 容器:
docker ps
=> 集装箱编号“4c721f1985bd”
查看本地物理机上的 docker 卷挂载点(https://docs.docker.com/engine/tutorials/dockervolumes/):
docker inspect -f {{.Mounts}} 4c721f1985bd
=> [{ /tmp/container-garren /tmp true rprivate}]
这告诉我本地物理机目录 /tmp/container-garren 已映射到 /tmp docker 卷目标。
了解本地物理机器目录 (/tmp/container-garren) 意味着无论 docker 容器是否正在运行,我都可以探索文件系统。这对于帮助我找出一些即使在容器停止运行后也不应该保留的残留数据至关重要。
解决方案 21:
对于 docker aufs 驱动程序:
该脚本将找到容器根目录(在docker 1.7.1和1.10.3上测试)
if [ -z "$1" ] ; then
echo 'docker-find-root $container_id_or_name '
exit 1
fi
CID=$(docker inspect --format {{.Id}} $1)
if [ -n "$CID" ] ; then
if [ -f /var/lib/docker/image/aufs/layerdb/mounts/$CID/mount-id ] ; then
F1=$(cat /var/lib/docker/image/aufs/layerdb/mounts/$CID/mount-id)
d1=/var/lib/docker/aufs/mnt/$F1
fi
if [ ! -d "$d1" ] ; then
d1=/var/lib/docker/aufs/diff/$CID
fi
echo $d1
fi
解决方案 22:
另一个技巧是使用原子工具来做类似的事情:
mkdir -p /path/to/mnt && atomic mount IMAGE /path/to/mnt
Docker 镜像将被挂载到/path/to/mnt以供您检查。
解决方案 23:
对于已经运行的容器,您可以执行以下操作:
dockerId=$(docker inspect -f {{.Id}} [docker_id_or_name])
cd /var/lib/docker/btrfs/subvolumes/$dockerId
您需要以 root 身份才能进入该目录。如果您不是 root,请在运行该命令之前尝试“sudo su”。
编辑:按照 v1.3,参见 Jiri 的回答 - 它更好。
解决方案 24:
我更喜欢用以下方式来了解容器内部的情况:
暴露-p 8000
docker run -it -p 8000:8000 image
在其中启动服务器
python -m SimpleHTTPServer
解决方案 25:
很多时候我只需要探索 docker 文件系统,因为我的构建无法运行,所以docker run -it <container_name> bash
不切实际。我也不想浪费时间和内存来复制文件系统,所以docker cp <container_name>:<path> <target_path>
也不切实际。
ls
虽然可能不太传统,但我建议使用Dockerfile 中的最后一个命令进行重建:
CMD [ "ls", "-R" ]
解决方案 26:
我有一个未知的容器,它正在执行一些生产工作量并且不想运行任何命令。
因此,我使用了docker diff。
这将列出容器已更改的所有文件,因此适合探索容器文件系统。
要获取仅一个文件夹,您只需使用 grep:
docker diff <container> | grep /var/log
它不会显示来自 docker 镜像的文件。根据您的使用情况,这可能会有帮助,也可能没有帮助。
解决方案 27:
如果您使用 AUFS 存储驱动程序,则可以使用我的docker-layer脚本来查找任何容器的文件系统根(mnt)和读写层:
# docker-layer musing_wiles
rw layer : /var/lib/docker/aufs/diff/c83338693ff190945b2374dea210974b7213bc0916163cc30e16f6ccf1e4b03f
mnt : /var/lib/docker/aufs/mnt/c83338693ff190945b2374dea210974b7213bc0916163cc30e16f6ccf1e4b03f
编辑 2018-03-28 : docker-layer 已被docker-backup
取代
解决方案 28:
我找到了最简单的一体化解决方案,可以在几乎任何正在运行的容器中使用 GUI 应用程序查看、编辑、复制文件。
mc 在docker中编辑文件
在容器内安装 mc 和 ssh:,
docker exec -it <container> /bin/bash
然后使用提示安装 mc 和 ssh 包在同一个 exec-bash 控制台中,运行
mc
按 ESC,然后按 9,然后按 ENTER 打开菜单并选择“Shell link...”
使用“Shell link...”通过其 IP 地址打开基于 SCP 的文件系统访问任何运行 ssh 服务器的主机(包括运行 docker 的主机)
在图形用户界面中完成你的工作
这种方法解决了权限、快照隔离等所有问题,允许直接复制到任何机器,对我来说是最愉快的使用方法
解决方案 29:
虽然来晚了,但 2022 年我们有了VS Code
解决方案 30:
docker exec
在正在运行的容器中运行命令的命令可以在多种情况下提供帮助。
用法:docker exec [选项] 容器命令 [参数...]
在正在运行的容器中运行命令
选项:
-d, --detach 分离模式:在后台运行命令
--detach-keys 字符串 覆盖分离的键序列
容器
-e, --env 列表 设置环境变量
-i, --interactive 即使未连接也保持 STDIN 开放
--privileged 为命令提供扩展权限
-t, --tty 分配一个伪 TTY
-u, --user 字符串用户名或 UID(格式:
[:])
-w, --workdir 字符串容器内的工作目录
例如 :
在 bash 中访问正在运行的容器文件系统:
docker exec -it 容器ID bash
在 bash 中以 root 身份访问正在运行的容器文件系统以获得所需的权限:
docker exec -it -u root 容器ID bash
这对于能够在容器中以 root 身份执行某些处理特别有用。
在 bash 中访问具有特定工作目录的正在运行的容器文件系统:
docker exec -it -w /var/lib 容器ID bash
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件