要进入虚拟机内部的Docker容器,最直接的办法是分两步走:先用SSH登录到那台虚拟机,然后在虚拟机终端里用docker exec -it 容器名 /bin/bash(或/bin/sh)进入该容器。这是绝大多数场景下最常用、也最不容易出错的操作路径,下面我把这条路径拆开,从命令选择到具体执行,再到退出方式和常见坑,一次讲清楚。
docker进入容器命令怎么用?先分清exec和attach
很多人一上来就纠结:docker exec和docker attach都是“进入容器”,到底该用哪个?答案是:想正常操作容器内部,用docker exec;想怼到容器主进程面前看实时输出,才考虑docker attach,这两者底层逻辑完全不同,用错会导致你明明进了容器,一按exit却把容器停掉了。
虚拟机里进入docker容器的完整操作流程
假设你有一台虚拟机,IP是168.1.10,里面跑着Docker引擎,现在想进入其中一个正在运行的容器,实际操作分以下三步:
- 第一步:登录虚拟机,在你的本地终端执行
ssh user@192.168.1.10,输入密码后进入虚拟机Shell,如果虚拟机是Windows Server,也可以先通过远程桌面进去,再打开PowerShell或CMD。 - 第二步:查看容器列表,在虚拟机终端执行
docker ps,你会看到类似这样的输出:
| 列名 | 含义 |
|---|---|
| CONTAINER ID | 容器短ID,可用于指定容器 |
| IMAGE | 镜像名 |
| COMMAND | 容器启动时执行的命令 |
| STATUS | 运行状态,Up表示正在运行 |
| PORTS | 端口映射 |
| NAMES | 容器名字,也叫“别名” |
记住你要进的容器的 NAMES 或 CONTAINER ID,比如web_app或1a2b3c。
- 第三步:执行docker exec进入容器,输入:
docker exec -it web_app /bin/bash
如果看到root@容器ID:/#这样的提示符,说明你已经成功进入容器内部,此时你是在虚拟机里,又进了一层容器,相当于“套娃”了两层。退出这个容器时,输入exit只会退回虚拟机Shell,不会把容器停掉,因为
exec创建的是一个独立的新进程。
为什么推荐exec而不是attach?
docker attach是把你的标准输入输出直接连接到容器的PID 1进程上,举个例子:一个容器的主进程是Nginx,attach进去以后你会看到Nginx的访问日志不断刷屏,但你无法正常执行ls、cat这些命令,如果你在这个会话里按Ctrl+C或输入exit,很可能直接把容器的主进程杀掉,导致容器停止,而exec则是“复制”一个子进程到容器里,它和主进程是平级关系,退出子进程不影响容器运行,行业共识认为,日常调试和操作容器时,exec是更安全的选择。
容器里没有bash怎么办?
有些精简镜像(比如Alpine、busybox)内部没有/bin/bash,这时你可能会遇到:
OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: "/bin/bash": stat /bin/bash: no such file or directory
解决方案很简单:改用/bin/sh,命令变成:
docker exec -it web_app /bin/sh
sh是几乎所有Linux容器都有的最小Shell,兼容性最好,如果连sh都没有,那镜像太极端了,考虑用docker exec -it web_app ls /bin看看可用工具,或者直接改用nsenter进入容器命名空间,但这属于高级玩法,日常用不到。
进入容器以后怎么退出?别把服务搞崩了
很多人在这个环节吃过亏,明明只是想看一眼容器里的配置文件,结果退出时把整个容器关了,下面按不同的进入方式给出对应的退出方法。
用exit退出exec会话
如果你是使用docker exec -it进入的容器,那么退出非常优雅:在容器Shell里直接输入exit然后回车,或者按Ctrl+D,这个操作只结束当前exec进程,容器主进程原封不动,你可以放心大胆退出,下次再用相同命令进去就行。
用Ctrl+P+Q从attach分离
如果你因为某些原因用了docker attach,或者用docker run -it启动了一个容器并进入了它的主进程,这时不能随便exit,正确做法是先按Ctrl+P,然后按Ctrl+Q,这个组合键叫做“detach”,意思是让容器在后台继续运行,而你退出容器终端回到宿主机,如果忘记这个组合键直接
exit,容器主进程会收到退出信号,通常会停止容器。能不用attach就别用,这是很多老手给你的最实在建议。
在虚拟机里,退出容器后还要退出虚拟机吗?
是的,结构要理清,你在虚拟机Shell里执行了exit退出容器,会回到虚拟机终端,随后如果你想彻底回到本地电脑,再执行一次exit退出SSH会话,这两层退出是独立的,别少了一步。
docker exec进入容器的常见坑与排查
来自实际运维中经常踩到的坑,如果你输入命令后没反应,或者报错,对照下面几个方向排查。
报错“Container is not running”
你的docker ps -a能看到容器,但docker exec却报:
Error response from daemon: Container xxx is not running
原因是这个容器已经退出,状态是Exited。docker exec只能进入正在运行的容器,就像你不能敲开一扇锁着的门,解决方法是先启动容器:
docker start web_app
然后再执行docker exec,如果容器每次启动都立即崩溃,那要先看日志:
docker logs web_app
找到崩溃原因,可能是环境变量没有、端口冲突,或者依赖的服务没起来。
权限问题:docker: permission denied
在虚拟机里执行docker ps或docker exec时,有时会看到:
docker: permission denied. Are you trying to connect to a Docker daemon socket?
这是因为你的当前系统用户不在docker用户组里,Docker引擎默认只允许root和有docker组权限的用户访问socket,两个解决办法:
- 临时加
sudo:sudo docker exec -it web_app /bin/bash - 永久解决:把当前用户加入docker组,执行
sudo usermod -aG docker $USER,然后退出SSH重新登录生效,注意,加入docker组等同于获得root权限,生产环境谨慎使用。
混淆了“进入虚拟机”和“进入容器”
这个场景非常典型:你本地已经装了一个Docker Desktop,想进入云端某个容器,结果直接在自己电脑上执行docker exec,当然找不到容器,要知道,docker exec命令是发给当前宿主机上的Docker daemon的,如果容器在虚拟机里,你需要先SSH进那台虚拟机,再在那个环境里执行docker命令,有时候还要注意远程Docker配置,比如通过
DOCKER_HOST或context切换,但最常见的还是“登录到对应机器”这一步。
通过SSH端口映射间接访问容器
还有一个常被问到的场景:虚拟机只开放了SSH端口,但容器内的业务端口(比如8080)没映射到公网,这时你想直接进容器?其实需要先SSH到虚拟机,再在虚拟机里用docker exec操作,或者把容器端口用-p映射出来再访问。没有捷径,先上虚拟机,再进容器是通用的逻辑。
Q&A:关于docker进入容器命令的三个高频问题
问题1:docker exec后面用容器ID还是容器名字?
都可以,用docker exec -it 容器ID或者docker exec -it 容器名,效果一样,为了可读性和避免记错,建议用NAMES那一列的名字,比如web_app,如果你同时跑多个相同镜像的容器,用ID更精确,可以用docker ps --format "table {{.Names}}t{{.ID}}t{{.Status}}"来格式化显示列表。
问题2:进入容器后,如何往容器里拷贝文件?
不用先进入容器再拷贝,在虚拟机终端里直接使用docker cp或docker cp命令:把本地文件拷入容器,用docker cp ./test.txt web_app:/tmp/;把容器文件拷出来,用docker cp web_app:/tmp/test.txt ./,这个命令在容器停止时也可以使用,但稳妥起见建议容器在运行状态。
问题3:docker attach和docker exec能混用吗?
可以,但没必要。attach和exec操作的是容器内部的两个不同会话,一个容器可以同时有多个exec会话,也可以有一个attach会话,如果你在attach会话里发现需要执行其他命令,不建议直接操作,而是另开一个终端用exec进去,这样互不干扰,核心原则始终是:exec用于操作,attach用于观察主进程输出。
回到开头那句话:进入虚拟机内部的容器,本质上就是“先到虚拟机,再进容器”,用docker exec -it配合/bin/bash或/bin/sh,能解决绝大多数需求,记住exit退出exec不会停止容器,Ctrl+P+Q退出attach不会停止容器,就能避开最伤脑筋的坑,只要环境畅通,这几条命令足够你在任何一台带Docker的虚拟机里进出自如。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/768376.html




