docker attach和docker exec之间的区别

时间:2015-06-21 02:23:10

标签: docker exec docker-exec

两者都可以在容器中执行命令。 两者都可以分离容器。

那么docker exec和docker attach之间的真正区别是什么?

4 个答案:

答案 0 :(得分:68)

有一个commit PR添加到doc:

  

注意:此命令(attach)不适用于在容器中运行新进程。   请参阅:docker exec

Docker. How to get bash\ssh inside runned container (run -d)?”的答案说明了不同之处:

  

(docker> = 1.3)如果我们使用docker attach,我们只能使用一个shell实例
  因此,如果我们想要使用容器shell的新实例打开新终端,我们只需要运行docker exec

     

如果使用/bin/bash命令启动了docker容器,则可以使用attach访问它,如果没有,则需要执行命令以使用{在容器内创建bash实例{1}}。

this issue中所述:

  
      
  • 附件不是用于在容器中运行额外的东西,而是用于附加到正在运行的进程。
  •   
  • exec”专门用于在已启动的容器中运行新事物,无论是shell还是其他进程。
  •   

同样的问题补充说:

  

虽然docker exec命名不好,特别是因为LXC命令attach(更类似lxc-attach,但LXC特定),它确实具有字面附加的特定目的你到Docker开始的过程。
  根据流程的不同,行为可能会有所不同,例如附加到docker exec <container> /bin/sh会给你一个shell,但是附加到redis-server就像你刚刚直接启动redis一样没有守护进程。

答案 1 :(得分:12)

当使用/ bin / bash启动容器时,它将成为容器 PID 1 ,并且docker attach用于获取容器的PID 1内部。所以 docker attach&lt; container-id&gt; 将带你进入bash终端,就像我们在启动容器时提到的PID 1一样。从容器中退出将停止容器。

docker exec 命令中,您可以指定要输入的shell。它不会将您带到容器的PID 1。它将为bash创建一个新进程。 docker exec -it&lt; container-id&gt; bash的即可。 从容器中退出不会阻止容器。

您还可以使用 nsenter 输入内部容器。 nsenter -m -u -n -p -i -t&lt;容器的pid&gt; 您可以使用以下命令找到容器的PID:docker inspect&lt; container-id&gt; | grep PID

注意:如果您已使用-d标志启动容器,则退出容器将不会停止容器,无论您使用attach还是exec进入容器。

答案 2 :(得分:1)

正如迈克尔·孙(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

当然,PIDPPID和其他值在您的情况下会有所不同。您可以使用其他工具和实用程序,例如pstreetophtop来查看PIDPPID的列表。

PIDPPID表示进程ID和父进程ID。当我们创建并使用命令/bin/sh启动容器时,该过程开始。现在,运行命令docker attach busybox。这会将容器的标准输入/输出/错误流附加到您的终端。

在附加容器之后,通过运行命令sh创建一个Shell会话。按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仅连接了标准输入/输出/容器内部主要过程的错误与当前端子的相应标准输入/输出/错误的对应关系。

答案 3 :(得分:0)

Docker exec在容器环境中执行一个新命令/创建一个新进程,而docker attach只是将容器内主进程(带有PID 1)的标准输入/输出/错误连接到相应的标准输入/输出/当前终端错误(您用于运行命令的终端)。

容器是一个隔离的环境,某些进程在该环境中运行。具体地说,容器具有自己的文件系统空间和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”,则您已经在容器内启动了两个新进程,它们彼此之间以及与主进程之间都没有关系,因此可以安全地退出它们