目录

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/

🍵 若本篇文章帮到了你

不必多,一杯茶的心意,就是我继续写作的动力 🌿

微信 / 支付宝收款码