我注意到 docker 我需要了解容器内发生了什么或其中存在哪些文件。一个例子是从 docker index 下载图像——你不知道图像包含什么,因此无法启动应用程序。
理想的情况是能够通过 ssh 进入它们或等效的。是否有工具可以做到这一点,或者我对 docker 的概念化认为我应该能够做到这一点是错误的。
docker exec <container> bash
。因此,您只需在容器内打开一个外壳。
docker exec <container> ls <dir path>
和 docker exec <container> cat <file path>
。但是,对于 bash,请添加 -it
选项。
docker image save image_name > image.tar
,如@Gaurav24 的响应中所示。
这里有几种不同的方法......
A)使用 docker exec(最简单)
Docker 1.3 或更高版本支持与 nsenter
类似的命令 exec
。此命令可以在已经运行的容器中运行新进程(容器必须已经运行 PID 1 进程)。您可以运行 /bin/bash
来探索容器状态:
docker exec -t -i mycontainer /bin/bash
见Docker command line documentation
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
,见 Why you don't need to run SSHd in your Docker containers
简短的版本是:使用 nsenter,您可以将 shell 放入现有容器中,即使该容器不运行 SSH 或任何类型的特殊用途守护程序
更新:探索!
这个命令应该让你探索一个正在运行的 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 返回中查找入口点或 cmd。
注意:此答案依赖于存在的常用工具,但如果没有 bash
shell 或 ls
等常用工具,如果您有权访问 { 3}:高山的例子:
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-compose exec documentation
docker exec -ti <name> powershell
(source)
docker exec -ti <name> cmd
工作。对于像我这样的其他新手,请确保使用来自 docker ps
的容器实例名称(类似于 070494393ca5),而不是您为其分配的可读名称。
如果您的容器已停止或没有外壳(例如 installation guide 中提到的 hello-world
或非 alpine
traefik
),这可能是探索文件系统的唯一可能方法。
您可以将容器的文件系统归档到 tar 文件中:
docker export adoring_kowalevski > contents.tar
或列出文件:
docker export adoring_kowalevski | tar t
请注意,根据图像,可能需要一些时间和磁盘空间。
export
示例的一个变体恰如其分:docker export adoring_kowalevski | tar tf -
f -
在命令末尾, tar 默认情况下从标准输入读取。只需 docker export adoring_kowalevski | tar t
即可。
tar f
的默认值取决于一个人的配置。一部分是 TAPE
环境变量。其他的则作为构建的一部分进行控制。最终结果是,永远不要假设它读取 stdin 或写入 stdout,但始终明确说明。
最受好评的答案是在容器实际启动时为我工作,但是当它无法运行并且您例如想要从容器中复制文件时,这已经救了我:
docker cp <container-name>:<path/inside/container> <path/on/host/>
感谢 docker cp (link),您可以直接从容器中复制,因为它是文件系统的任何其他部分。例如,恢复容器内的所有文件:
mkdir /tmp/container_temp
docker cp example_container:/ /tmp/container_temp/
请注意,您无需指定要递归复制。
容器创建之前:
如果您要探索安装在容器内的图像的结构,您可以这样做
sudo docker image save image_name > image.tar
tar -xvf image.tar
这将使您可以看到图像的所有层及其在 json 文件中的配置。
容器创建后:
为此,上面已经有很多答案。我首选的方法是-
docker exec -t -i container /bin/bash
bash
时输入 sh
提示。
容器的文件系统在docker的data文件夹下,一般在/var/lib/docker。为了启动和检查正在运行的容器文件系统,请执行以下操作:
hash=$(docker run busybox)
cd /var/lib/docker/aufs/mnt/$hash
现在当前工作目录是容器的根目录。
您可以使用 Dive 与 TUI 交互地查看图像内容
https://github.com/wagoodman/dive
https://i.stack.imgur.com/OLFEC.png
尝试使用
docker exec -it <container-name> /bin/bash
bash 可能没有实现。为此,您可以使用
docker exec -it <container-name> sh
在运行 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
devicemapper
目录)。该文件存在于 /var/lib/docker/overlay/<a sha256 apparently/<upper or merged>/...
下。我不确定在那里访问文件的便携性/安全性
direct-lvm
。
在我的情况下,除了 sh
之外,容器中不支持任何 shell。所以,这就像一个魅力
docker exec -it <container-name> sh
我使用了另一个与 aufs/devicemapper 无关的肮脏技巧。
我查看容器正在运行的命令,例如 docker ps
,如果它是 apache 或 java
,我只需执行以下操作:
sudo -s
cd /proc/$(pgrep java)/root/
瞧,你在容器里面。
基本上,只要该进程由容器运行,您就可以作为根 cd 进入 /proc/<PID>/root/
文件夹。当心符号链接在使用该模式时没有意义。
仅适用于 LINUX
我使用的最简单的方法是使用 proc dir,容器必须正在运行才能检查 docker 容器文件。
找出容器的进程ID(PID)并将其存储到某个变量中 PID=$(docker inspect -f '{{.State.Pid}}' your-container-name-here) 确保容器进程正在运行, 并使用变量名进入容器文件夹 cd /proc/$PID/root
如果你想通过 dir 而不找出 PID 号,只需使用这个长命令
cd /proc/$(docker inspect -f '{{.State.Pid}}' your-container-name-here)/root
提示:
进入容器后,你所做的一切都会影响容器的实际进程,比如停止服务或更改端口号。
希望能帮助到你
笔记:
此方法仅在容器仍在运行时有效,否则,如果容器已停止或删除,该目录将不再存在
docker cp
。相反,需要一条我可以通过 scp
从主机中提取的直接路径,而您的解决方案为我提供了一条。谢谢!
投票最多的答案是好的,除非您的容器不是实际的 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 身份运行它。
现有答案都没有解决容器退出(并且无法重新启动)和/或没有安装任何外壳(例如无发行版)的情况。只要您具有对 Docker 主机的 root 访问权限,此方法就可以工作。
对于真正的手动检查,首先找出层 ID:
docker inspect my-container | jq '.[0].GraphDriver.Data'
在输出中,您应该看到类似
"MergedDir": "/var/lib/docker/overlay2/03e8df748fab9526594cfdd0b6cf9f4b5160197e98fe580df0d36f19830308d9/merged"
导航到此文件夹(以 root 身份)以查找容器文件系统的当前可见状态。
在较新版本的 Docker 上,您可以运行 docker exec [container_name]
,它在容器内运行 shell
因此,要获取容器中所有文件的列表,只需运行 docker exec [container_name] ls
我想这样做,但我无法执行到我的容器中,因为它已经停止并且由于我的代码中的一些错误而没有再次启动。
对我有用的是简单地将整个容器的内容复制到一个新文件夹中,如下所示:
docker cp container_name:/app/ new_dummy_folder
然后,我可以像使用普通文件夹一样探索该文件夹的内容。
这将为图像启动一个 bash 会话:
docker run --rm -it --entrypoint=/bin/bash
对我来说,这个很好用(感谢最后的评论指出目录 /var/lib/docker/):
chroot /var/lib/docker/containers/2465790aa2c4*/root/
这里,2465790aa2c4 是正在运行的容器的短 ID(由 docker ps 显示),后跟一个星号。
对于 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
即使容器没有运行,这个答案也会帮助那些想要探索 docker 卷文件系统的人(比如我自己)。
列出正在运行的 docker 容器:
docker ps
=> 容器 ID“4c721f1985bd”
查看本地物理机 (https://docs.docker.com/engine/tutorials/dockervolumes/) 上的 docker 卷安装点:
docker inspect -f {{.Mounts}} 4c721f1985bd
=> [{ /tmp/container-garren /tmp true rprivate}]
这告诉我本地物理机目录 /tmp/container-garren 映射到 /tmp docker 卷目标。
了解本地物理机目录 (/tmp/container-garren) 意味着无论 docker 容器是否正在运行,我都可以探索文件系统。这对于帮助我找出即使在容器未运行后也不应该保留的一些残留数据至关重要。
对于已经运行的容器,您可以执行以下操作:
dockerId=$(docker inspect -f {{.Id}} [docker_id_or_name])
cd /var/lib/docker/btrfs/subvolumes/$dockerId
您需要成为 root 才能 cd 进入该目录。如果您不是 root,请在运行命令之前尝试“sudo su”。
编辑:在 v1.3 之后,请参阅 Jiri 的答案 - 更好。
另一个技巧是使用 atomic 工具执行以下操作:
mkdir -p /path/to/mnt && atomic mount IMAGE /path/to/mnt
Docker 映像将被挂载到 /path/to/mnt 以供您检查。
如果您使用的是 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
我更喜欢了解容器内部发生的事情的方法是:
暴露 -p 8000 docker run -it -p 8000:8000 image 在里面启动服务器 python -m SimpleHTTPServer
如果您使用的是 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
在正在运行的容器中运行命令的 docker exec
命令可以在多种情况下提供帮助。
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...] Run a command in a running container Options: -d, --detach Detached mode: run command in the background --detach-keys string Override the key sequence for detaching a container -e, --env list Set environment variables -i, --interactive Keep STDIN open even if not attached --privileged Give extended privileges to the command -t, --tty Allocate a pseudo-TTY -u, --user string Username or UID (format: [:]) -w, --workdir string Working directory inside the container
例如 :
1) 在 bash 中访问正在运行的容器文件系统:
docker exec -it containerId bash
2) 以 root 身份访问正在运行的容器文件系统以获得所需的权限:
docker exec -it -u root containerId bash
这对于能够在容器中以 root 身份进行一些处理特别有用。
3) 使用 bash 访问具有特定工作目录的正在运行的容器文件系统:
docker exec -it -w /var/lib containerId bash
很多时候我只需要探索 docker 文件系统,因为我的构建不会运行,所以 docker run -it <container_name> bash
是不切实际的。我也不想浪费时间和内存复制文件系统,所以 docker cp <container_name>:<path> <target_path>
也是不切实际的。
虽然可能是非正统的,但我建议使用 ls
作为 Dockerfile 中的最终命令重新构建:
CMD [ "ls", "-R" ]
我有一个未知的容器,它正在做一些生产工作并且不想运行任何命令。
所以,我使用了 docker diff。
这将列出容器已更改的所有文件,因此非常适合探索容器文件系统。
要仅获取一个文件夹,您可以使用 grep:
docker diff <container> | grep /var/log
它不会显示来自 docker 映像的文件。根据您的用例,这可能有帮助或没有帮助。
您可以使用以下命令在容器内运行 bash: $ docker run -it ubuntu /bin/bash
几乎我使用的所有容器都有 Python,所以我附加到容器上,
pip install jupyterlab
cd /
jupyter lab --allow-root
我 ^单击 Jupyter Lab 服务器提供的链接,在主机的浏览器中,我拥有完美的文件系统 GUI,可以打开各种文件(ipnb、py、md(预览中)...)
干杯G。
Option 1
。RUN apk update && apk add bash
(大小:~4MB)docker exec -t -i mycontainer /bin/sh