MJL*_*MJL 69 exec docker docker-exec
两者都能够在容器中执行命令.两者都可以分离容器.
那么docker exec和docker attach之间的真正区别是什么?
Von*_*onC 76
有一个提交PR添加到文档中:
注意:此命令(
attach)不用于在容器中运行新进程.见:docker exec.
" Docker.如何在runned container(run -d)中获取bash\ssh ? " 的答案说明了不同之处:
(docker> = 1.3)如果我们使用
docker attach,我们只能使用一个shell实例.
因此,如果我们想要使用容器shell的新实例打开新终端,我们只需要运行docker exec如果使用
/bin/bash命令启动docker容器,则可以使用attach访问它,如果没有,则需要执行命令以在容器内创建bash实例exec.
如本期所述:
- Attach不是用于在容器中运行额外的东西,而是用于附加到正在运行的进程.
- "
docker exec"专门用于在已经启动的容器中运行新事物,无论是shell还是其他进程.
同样的问题增加了:
虽然
attach没有很好的命名,特别是因为LXC命令lxc-attach(更为类似docker exec <container> /bin/sh,但LXC特定),它确实有一个特定的目的,字面上将您附加到Docker启动的过程.
根据进程的不同,行为可能会有所不同,例如attach to/bin/bash会给你一个shell,但是附加到redis-server就像你刚刚开始redis而没有daemonizing.
Sam*_*shi 19
当使用/ bin/bash启动容器时,它将成为容器PID 1,并且docker attach用于获取容器的PID 1内部.所以docker attach <container-id>将带你进入bash终端,就像我们在启动容器时提到的PID 1一样.从容器中退出将停止容器.
而在docker exec命令中,您可以指定要输入的shell.它不会将您带到容器的PID 1.它将为bash创建一个新进程. docker exec -it <container-id> bash.从容器中退出不会阻止容器.
您还可以使用nsenter输入内部容器. nsenter -m -u -n -p -i -t <容器的pid> 您可以使用以下命令找到容器的PID:docker inspect <container-id> | grep PID
注意:如果您已使用-d标志启动容器,则退出容器将不会停止容器,无论您使用attach还是exec进入容器.
Kar*_*han 15
正如迈克尔孙在他的回答中所说
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
Run Code Online (Sandbox Code Playgroud)
当然,PID,PPID和其他值在您的情况下会有所不同。您可以使用其他工具和实用程序,以及像pstree,top,htop看到的名单PID和PPID。
该PID和PPID指进程ID和父进程ID。当我们使用命令创建和启动我们的容器时,这个过程就开始了/bin/sh。现在,运行命令docker attach busybox。这会将容器的标准输入/输出/错误流附加到您的终端。
附加容器后,通过运行命令创建一个 shell 会话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
Run Code Online (Sandbox Code Playgroud)
但是这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
Run Code Online (Sandbox Code Playgroud)
第PPID一个和第三个进程是一样的,确认docker exec在容器环境中创建一个新进程,同时docker attach只是将容器内部主进程的标准输入/输出/错误连接到当前对应的标准输入/输出/错误终端。
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-keys 来 detach),你会看到两个终端都退出了。但是如果你在两个终端中运行“docker exec –it XXX /bin/bash”,你已经在容器内启动了两个新进程,并且它们彼此之间以及与主进程无关,你可以安全地退出它们.