两者都将能够在容器中执行命令。两者都可以拆下容器。
那么docker exec和docker attach之间的真正区别是什么?
Answers:
有一个提交PR添加到文档中:
注意:此命令(
attach
)不适用于在容器中运行新进程。请参阅:docker exec
。
回答“ Docker。如何在运行的容器(run -d
)中获取bash \ ssh ? ”阐明了区别:
(docker> = 1.3)如果使用
docker attach
,则只能使用shell的一个实例。
因此,如果我们想使用容器外壳的新实例打开新终端,我们只需要运行docker exec
如果docker容器是使用
/bin/bash
命令启动的,则可以使用attach访问它,否则,您需要使用执行命令以在该容器内创建bash实例exec
。
如本期所述:
- Attach不是在容器中运行额外的东西,而是用于附加到正在运行的进程。
- “
docker exec
”专门用于在已启动的容器中运行新事物,无论是外壳还是其他进程。
相同的问题添加:
虽然
attach
名称不明确,尤其是由于LXC命令lxc-attach
(更类似于docker exec <container> /bin/sh
,但特定于LXC),但它确实具有将您真正地附加到Docker启动的进程的特定目的。
根据过程的不同,行为可能会有所不同,例如,附加到/bin/bash
会给您一个shell,但是附加到redis-server就像您直接在没有守护进程的情况下直接启动redis。
当使用/ bin / bash启动容器时,它将成为容器PID 1,而docker attach用于获取容器的PID 1。因此docker attach <container-id>将带您进入bash终端,因为它是我们启动容器时提到的PID 1。从容器中退出将停止容器。
而在docker exec命令中,您可以指定要输入的外壳。它不会带您到容器的PID 1。它将为bash创建一个新的过程。 docker exec -it <容器ID> bash。从容器中退出不会停止容器。
您也可以使用nsenter进入容器内部。 nsenter -m -u -n -p -i -t <容器的pid> 您可以使用以下命令找到容器的PID:docker inspect <容器的id> | grep PID
注意:如果使用-d标志启动了容器,则退出容器并不会停止容器,无论您使用attach还是exec进入容器。
正如迈克尔·孙(Michael Sun)在回答中所说的
docker exec
在容器环境中执行一个新命令/创建一个新过程,而docker attach
只是将容器内部主过程(带有PID 1)的标准输入/输出/错误连接到当前终端(终端)的相应标准输入/输出/错误您正在使用运行命令)。
我的回答将更多地集中在让您验证以上陈述并更清楚地理解它上。
打开一个终端窗口并运行命令docker run -itd --name busybox busybox /bin/sh
。busybox
如果尚不存在,该命令将拉取图像。然后,它将busybox
使用该图像使用名称创建一个容器。
您可以通过运行命令来检查容器的状态docker ps -a | grep busybox
。
如果运行docker top busybox
,您应该会看到类似以下的输出。
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
当然,根据您的情况PID
,PPID
和值将有所不同。您可以使用其他工具和实用程序,以及像pstree
,top
,htop
看到的名单PID
和PPID
。
该PID
和PPID
指进程ID和父进程ID。当我们创建并使用命令启动容器时,该过程开始/bin/sh
。现在,运行命令docker attach busybox
。这会将容器的标准输入/输出/错误流附加到您的终端。
附加容器后,通过运行命令创建外壳会话sh
。按CTRL-p CTRL-q
顺序。这将使终端与容器分离,并使容器保持运行状态。如果现在运行docker top busybox
,您应该在列表中看到两个进程。
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
但是这PPID
两个过程的将有所不同。实际上,PPID
第二个过程的过程PID
与第一个过程的过程相同。第一个进程充当我们刚创建的Shell会话的父进程。
现在开始 docker exec -it busybox sh
。进入容器后,busybox
通过运行命令在另一个终端窗口中检查容器的运行进程列表docker top busybox
。你应该看到这样的东西
UID PID PPID C STIME TTY TIME CMD
root 7469 7451 0 11:40 pts/0 00:00:00 /bin/sh
root 7737 7469 0 11:43 pts/0 00:00:00 sh
root 7880 7451 0 11:45 pts/1 00:00:00 sh
第PPID
一个和第三个过程的相同,这确认docker exec
了在容器环境中创建了一个新过程,而docker attach
只是将容器内部主过程的标准输入/输出/错误连接到当前的相应标准输入/输出/错误。终奌站。
Docker exec在容器环境中执行一个新命令/创建一个新进程,而docker attach只是将容器内主进程(带有PID 1)的标准输入/输出/错误连接到当前的相应标准输入/输出/错误。 terminal(用于运行命令的终端)。
容器是一个隔离的环境,某些进程在该环境中运行。具体来说,容器具有自己的文件系统空间和PID空间,这些空间与主机容器和其他容器隔离。当使用“ docker run –it…”启动容器时,主进程将具有伪tty和STDIN保持打开状态。在tty模式下连接时,您可以使用可配置的键序列从容器分离(并使它保持运行状态)。默认序列为CTRL-p CTRL-q。您可以使用--detach-keys选项或配置文件来配置键序列。您可以使用docker attach重新连接到分离的容器。
Docker exec只是在容器环境内部启动了一个新过程,也就是说,它属于容器的PID空间。
例如,如果您使用“ docker run –dit XXX / bin / bash”启动容器,则可以使用两个不同的终端将其连接到容器(主进程)。在一个端子中输入时,可以看到它出现在另一端子中,因为两个端子都连接到同一tty。请注意,您现在处于容器的主进程中,如果键入“ exit”,则将退出容器(因此请注意,使用detach-key来分离),并且您将看到两个终端都退出了。但是,如果您在两个终端上运行“ docker exec –it XXX / bin / bash”,则在容器内启动了两个新进程,它们彼此之间,与主进程之间都没有关系,因此可以安全地退出它们。
nsenter
。你能详细说明吗?解释选项将是有序的。为什么不输入所有名称空间?为什么要这些特殊的?