1. 进入容器前,先搞清楚你面对的是一个什么“环境”
1.1 容器不是一台微型虚拟机
我在帮团队做 Docker 入门培训时,几乎每次都会被问到同一个问题:“怎么进到容器里面看看?”提问的人通常脑海里已经有一个画面:容器相当于一台跑起来的小服务器,桌面双击一个终端,或者 SSH 连上去,就能像操作虚拟机一样自由查看。
这个画面不能说全错,但会带来很多错误期待。虚拟机里装的是完整操作系统,你有 init 系统、systemd、完整的目录结构和一堆系统工具。容器则完全不同,它本质上是宿主机上的一个进程,只是通过 Linux 的 namespace 和 cgroup 给它单独划出了 PID、网络、文件系统、CPU 和内存的“幻觉自治区域”。你执行 docker exec -it <容器ID> bash 进入容器时,不是“登录到了一台新机器”,而是“把这个 bash 进程塞进了目标容器已有的 namespace 里”,让这个 bash 和容器里的主进程共享同一套隔离视图。
这个认知差别会影响你后续所有操作。比如,容器里没有 systemd、没有 sshd、甚至可能连 ps、top、vim 都没有,因为镜像为了体积和安全性,早就把这类工具精简掉了。你进去后面对的是一个只有一个或几个进程的极简环境,而不是一个功能齐全的操作系统。所以当你发现 apt 都装不了软件时,不要怀疑自己进错了地方,这正是容器的正常形态。
1.2 PID 1 进程决定容器的生死
另一个容易忽略的关键点,是容器里的 PID 1。Docker 容器启动时,你在 docker run 后面指定的命令会变成容器内的 1 号进程。这个进程不是普通的 1 号进程,它承担着“容器存活”的职责:一旦 PID 1 进程退出,无论容器里还有没有其他子进程,整个容器都会被 Docker 判定为结束。
举个最常见的例子:很多人写 docker run -d ubuntu 启动容器,然后发现容器秒退,docker ps 里什么都看不到,只能从 docker ps -a 里看到状态的 Exited。原因很简单,ubuntu 镜像默认的 CMD 是 bash,而 bash 在没有交互终端输入时立刻返回到退出状态,容器里最后一个前台进程结束了,容器自然就停了。
所以进入容器之前,你先得想明白:你现在看到的这个容器,它的 PID 1 到底是谁?想长期驻留,PID 1 就必须能持续挂起,比如 tail -f /dev/null、nginx -g "daemon off;" 这类前台阻塞命令。想进入容器调试,你也不是在“连接”什么,而是在“加入”,你的操作进程和你观察到的容器主进程之间,并不是像宿主机用户和后台服务那种松耦合关系。
1.3 常见的“错误期待”会导致的操作偏差
我总结了一下,因为没搞懂上面两点,新手通常会犯三类操作偏差:
- 用习惯 SSH 的方式,在容器里找
/etc/ssh/sshd_config,然后试图开启 sshd,其实压根没必要,docker exec就是你的 Remote Shell。 - 进入容器后直接敲
systemctl restart nginx,然后收到System has not been booted with systemd as init system,因为容器里根本没有 systemd。 - 在
docker attach里按了几下Ctrl+D,容器直接退出,后续日志全丢。
这些偏差的共同根源,是把容器当成了虚拟机。阅读本文时,请先把“容器是一台轻量虚拟机”这个念头放下。容器是进程,进入容器是把你的操作进程放进另一个进程的视野里。抱着这个基本认知去使用后面提到的命令,你会少踩很多坑。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 几十种命令里,真正需要掌握的四种进入方式
2.1 docker attach:能进去,但出来容易出事
docker attach 是 Docker 官方提供的最早期交互方式之一,它的作用是“把你的标准输入输出直接挂到容器的主进程上”。理解起来很简单:你看到的就是 PID 1 进程的终端输出,你的键盘输入也会直接送给 PID 1。
使用方式:
bash复制docker attach <容器ID或容器名>
比如我先启动一个 nginx 容器:
bash复制docker run -d --name web-demo nginx
docker attach web-demo
执行后,你能在屏幕上看到 nginx 的访问日志,这是因为 nginx 在容器内把日志写到了标准输出,而 docker attach 把你和这个标准输出接在了一起。
这看起来很方便,但它的危险点在于你的退出动作。在 attach 模式下,如果你直接按 Ctrl+C 或者输入 exit,这个信号会直接发给容器主进程,而绝大多数进程收到这个信号后会结束,容器随之停止。也就是说,你不是“退出了容器”,你是“把容器的 PID 1 杀了”。如果你只是想去容器里看一眼然后继续让它跑,请千万不要在 attach 里裸按 Ctrl+C,而是用我们后面会讲的 Ctrl+P+Q。
正因如此,我自己的建议是:日常工作中几乎不要用 docker attach。它更适合的场景是:你明确想观察一个前台进程的输出,并且已经做好了容器停止的准备。
2.2 docker exec:日常排查主力,也是我的默认选择
`docker
