进入 Docker 容器 Shell 的常用方法有哪些?
运行中的容器用 docker exec -it 容器名 bash/sh 进 shell;已停止的容器 commit 成镜像再跑;compose 用 docker compose exec 服务名 sh。distroless 无 shell 时用 cp/logs 替代。速查汇总。
速查:运行中的容器——docker exec -it <容器名> bash(没有 bash 用 sh);compose 项目——docker compose exec <服务名> sh;已停止的容器——exec 用不了,先 commit 成镜像再 run 进 shell,或用 docker cp 拷文件。
运行中的容器
docker exec -it myapp bash # Debian/Ubuntu 系
docker exec -it myapp sh # Alpine 等精简镜像
docker exec -u 0 -it myapp sh # 需要 root 时
退出输 exit,容器主进程不受影响。这是最常用、最推荐的方式。
compose 项目
docker compose ps # 确认服务名
docker compose exec web sh # 服务名,不是容器名
好处:不用记容器全名(项目前缀+序号),在哪台机器上写法都一样。
已停止的容器
exec 只对运行中的容器有效。已停止的:
# 方式一:commit 成快照镜像,起新容器看
docker commit myapp-stopped mysnapshot
docker run -it --rm mysnapshot sh
# 方式二:只想拿文件
docker cp myapp-stopped:/app/logs ./logs
# 方式三:看相对镜像改了什么
docker diff myapp-stopped
没有 shell 的镜像
distroless、scratch 基础镜像里没有 bash/sh,exec 会报 no such file:
docker cp拷进拷出docker logs看输出- K8s 环境用
kubectl debug挂 ephemeral 调试容器 - 构建时保留一个带 shell 的 debug 变体镜像(
myapp:debug)
一句话选择
| 场景 | 命令 |
|---|---|
| 日常排查 | docker exec -it 容器 sh |
| compose 项目 | docker compose exec 服务 sh |
| 停止的容器 | commit → run,或 cp |
| 无 shell 镜像 | cp / logs / debug 镜像 |
观测云对照
把"进容器"变成"查平台"。 日志、进程、资源用量都在观测云可查时,进容器更多是改配置等少数场景;减少 exec 也降低了人为误操作面。
常见问题(FAQ)
Q:exec 进去 hostname 显示一串哈希正常吗?
A:正常,那是容器 ID 短哈希,可 -h 名字 自定义。
Q:每次进去环境变量不全?
A:exec 继承主进程环境;手动 docker exec 的 shell 若缺变量,检查变量是不是写在某个 entrypoint 的 export 里只对子进程生效——exec 本身没问题。
Q:attach 和 exec 选哪个?
A:进 shell 排查一律 exec;attach 会接管主进程,Ctrl+C 可能把容器搞停。