探索 Docker 容器的文件系统

2024-10-09 09:10:00
admin
原创
80
摘要:问题描述:我注意到,在使用 docker 时,我需要了解容器内部发生了什么或容器中存在哪些文件。一个例子是从 docker 索引下载镜像 - 你不知道镜像包含什么,因此无法启动应用程序。最理想的是能够通过 ssh 进入它们或类似的东西。有没有工具可以做到这一点,或者我对 docker 的概念理解是错误的,认为...

问题描述:

我注意到,在使用 docker 时,我需要了解容器内部发生了什么或容器中存在哪些文件。一个例子是从 docker 索引下载镜像 - 你不知道镜像包含什么,因此无法启动应用程序。

最理想的是能够通过 ssh 进入它们或类似的东西。有没有工具可以做到这一点,或者我对 docker 的概念理解是错误的,认为我应该能够做到这一点。


解决方案 1:

这里有几种不同的方法...

A)使用 docker exec (最简单)

execDocker 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

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

注意:这个答案依赖于常用工具的存在,但如果没有bashshell 或常用工具,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 容器文件。

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

PID=$(docker inspect -f'{{.State.Pid}}' 你的容器名称在这里)

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

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:

我更喜欢用以下方式来了解容器内部的情况:

  1. 暴露-p 8000

docker run -it -p 8000:8000 image
  1. 在其中启动服务器

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中编辑文件

  1. 在容器内安装 mc 和 ssh:,docker exec -it <container> /bin/bash然后使用提示安装 mc 和 ssh 包

  2. 在同一个 exec-bash 控制台中,运行mc

  3. 按 ESC,然后按 9,然后按 ENTER 打开菜单并选择“Shell link...”

  4. 使用“Shell link...”通过其 IP 地址打开基于 SCP 的文件系统访问任何运行 ssh 服务器的主机(包括运行 docker 的主机)

  5. 在图形用户界面中完成你的工作

这种方法解决了权限、快照隔离等所有问题,允许直接复制到任何机器,对我来说是最愉快的使用方法

解决方案 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 字符串容器内的工作目录

例如 :

  1. 在 bash 中访问正在运行的容器文件系统:

docker exec -it 容器ID bash

  1. 在 bash 中以 root 身份访问正在运行的容器文件系统以获得所需的权限:

docker exec -it -u root 容器ID bash

这对于能够在容器中以 root 身份执行某些处理特别有用。

  1. 在 bash 中访问具有特定工作目录的正在运行的容器文件系统:

docker exec -it -w /var/lib 容器ID bash

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   601  
  华为IPD与传统研发模式的8大差异在快速变化的商业环境中,产品研发模式的选择直接决定了企业的市场响应速度和竞争力。华为作为全球领先的通信技术解决方案供应商,其成功在很大程度上得益于对产品研发模式的持续创新。华为引入并深度定制的集成产品开发(IPD)体系,相较于传统的研发模式,展现出了显著的差异和优势。本文将详细探讨华为...
IPD流程是谁发明的   7  
  如何通过IPD流程缩短产品上市时间?在快速变化的市场环境中,产品上市时间成为企业竞争力的关键因素之一。集成产品开发(IPD, Integrated Product Development)作为一种先进的产品研发管理方法,通过其结构化的流程设计和跨部门协作机制,显著缩短了产品上市时间,提高了市场响应速度。本文将深入探讨如...
华为IPD流程   9  
  在项目管理领域,IPD(Integrated Product Development,集成产品开发)流程图是连接创意、设计与市场成功的桥梁。它不仅是一个视觉工具,更是一种战略思维方式的体现,帮助团队高效协同,确保产品按时、按质、按量推向市场。尽管IPD流程图可能初看之下显得错综复杂,但只需掌握几个关键点,你便能轻松驾驭...
IPD开发流程管理   8  
  在项目管理领域,集成产品开发(IPD)流程被视为提升产品上市速度、增强团队协作与创新能力的重要工具。然而,尽管IPD流程拥有诸多优势,其实施过程中仍可能遭遇多种挑战,导致项目失败。本文旨在深入探讨八个常见的IPD流程失败原因,并提出相应的解决方法,以帮助项目管理者规避风险,确保项目成功。缺乏明确的项目目标与战略对齐IP...
IPD流程图   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用