docker attach 卡住进不去?换成 exec 就好了
很多人第一次想进正在运行的容器,顺手就敲了 docker attach,结果屏幕直接卡死。
光标在那闪,啥也输不进去,按回车也没反应。
更坑的是,下意识来一个 Ctrl+C,容器没了。
这篇就把 docker attach 为什么会卡、以及正确的进容器方式讲清楚。
docker attach 到底连的是什么?
docker attach 连接的是容器主进程(PID 1)的标准输入、输出和错误流。
注意,它不是给你开一个新的 shell。
它只是把你的终端,挂到容器启动时那个进程上。
举个例子。
如果容器的主进程是一个 Nginx,或者一个常驻的 Go 服务,这些进程根本不读标准输入。
那你 attach 上去之后,敲什么都没用,看起来就是「卡住」了。
其实它没卡,是那个进程压根不理你。
为什么会感觉卡住、还容易误杀容器
主要是三个原因凑一块儿了。
第一,主进程不交互。
像 nginx -g 'daemon off;'、java -jar xxx、./server 这类前台常驻进程,不会响应键盘输入,自然没回显。
第二,信号会被透传。
docker attach 默认带 --sig-proxy=true,你按的 Ctrl+C(SIGINT)会直接发给 PID 1。
PID 1 一旦退出,整个容器就停了。
这就是为什么手一抖容器就挂的原因。
第三,退出方式反直觉。
想退出 attach 又不想停容器,得按 Ctrl+P 再按 Ctrl+Q 这个组合键。
这玩意儿不告诉你,基本没人猜得到。
正确姿势:用 docker exec 进容器
要进容器里敲命令、看日志、调试问题,用 docker exec 开一个新进程,而不是 attach 到老进程上。
## 不推荐:挂到主进程,容易卡、容易误杀
docker attach <容器ID或容器名>
## 推荐:在容器里新开一个交互式 bash
docker exec -it <容器ID或容器名> /bin/bash-it 是两个参数合写。
-i 保持标准输入打开,-t 分配一个伪终端,合起来才有正常的交互体验。
退出的时候直接 exit 或者 Ctrl+D 就行,关掉的只是这个新开的 shell,容器照常跑。
这一点和 attach 完全不一样,省心很多。
容器里没有 bash 怎么办?
精简镜像(比如 Alpine)经常不带 /bin/bash,这时候 exec 会报 executable file not found。
换成 sh 即可:
docker exec -it <容器ID或容器名> /bin/sh还不行就直接跑单条命令,连 shell 都不进:
## 直接看进程
docker exec <容器ID或容器名> ps aux
## 直接看某个文件
docker exec <容器ID或容器名> cat /etc/hosts调试小问题用这种一次性命令,比进交互式 shell 还快。
attach 和 exec 到底怎么选
下面这张表对照着看,基本不会再选错。
| 对比项 | docker attach | docker exec -it |
|---|---|---|
| 连接对象 | 容器主进程 PID 1 | 新开的子进程 |
| 能否交互 | 取决于主进程是否读 stdin | 能,开独立 shell |
| 退出影响 | Ctrl+C 可能停掉容器 | exit 只关自己开的 shell |
| 退出方式 | Ctrl+P Ctrl+Q(不停容器) | exit 或 Ctrl+D |
| 适用场景 | 看主进程前台实时输出 | 进容器排查、调试、执行命令 |
说白了,日常进容器干活,几乎都该用 exec。
attach 只在一种情况下顺手:你就是想看主进程那个前台进程在打什么日志。
如果就是要用 attach,怎么不被坑
确实有场景需要 attach,比如临时盯一下前台输出。
那加上 --sig-proxy=false,让 Ctrl+C 不再透传给容器:
docker attach --sig-proxy=false <容器ID或容器名>这样按 Ctrl+C 只断开你的连接,不会把容器主进程顺手杀掉。
退出还是老规矩,Ctrl+P 接 Ctrl+Q。
常见问题
Q1. docker attach 卡住了,怎么安全退出?
按 Ctrl+P 再按 Ctrl+Q,这个组合键会断开连接但保留容器运行。
千万别按 Ctrl+C,默认配置下它会把容器主进程也停掉。
Q2. docker exec 和 docker attach 有什么区别?
exec 在容器里新开一个进程(比如 bash),退出不影响容器;attach 是挂到已有的主进程 PID 1 上,操作不当会停容器。
进容器排查问题,优先用 exec。
Q3. 用 exec 报 executable file not found 是什么原因?
镜像里没有你指定的可执行文件,最常见是精简镜像不带 /bin/bash。
改用 /bin/sh 一般就能进去。
Q4. 容器主进程是后台服务,attach 上去没输出正常吗?
正常。
attach 连的是 PID 1 的标准流,如果这个进程不读 stdin、也没往 stdout 打东西,屏幕就会一直没反应,看着像卡住。
Q5. 想在容器里执行一条命令,不进交互式 shell 行不行?
可以,直接 docker exec <容器ID或容器名> <命令>,比如 docker exec web ps aux。
适合快速查状态,不用进 shell 再退出。
小结
docker attach 卡住,多数时候不是 bug,是它本来就连在不读输入的主进程上。
进容器干活,记住一句话:用 docker exec -it 开新 shell,别用 attach。
实在要 attach,加 --sig-proxy=false,退出用 Ctrl+P Ctrl+Q。
如果你在进容器、调试或者退出快捷键上还踩过别的坑,欢迎在评论区聊聊~~~
版权声明
未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!
本文原文链接: https://fiveyoboy.com/articles/docker-attach-stuck-use-exec/
备用原文链接: https://blog.fiveyoboy.com/articles/docker-attach-stuck-use-exec/
🍵 若本篇文章帮到了你
不必多,一杯茶的心意,就是我继续写作的动力 🌿