mirror of
https://github.com/yeasy/docker_practice.git
synced 2026-02-26 03:59:30 +00:00
7.2 KiB
7.2 KiB
进入容器
为什么需要进入容器
使用 -d 参数启动容器后,容器在后台运行。以下场景需要进入容器内部操作:
| 场景 | 示例 |
|---|---|
| 调试问题 | 查看日志、检查配置、排查错误 |
| 临时操作 | 执行数据库迁移、清理缓存 |
| 检查状态 | 查看进程、网络连接、文件系统 |
| 开发测试 | 交互式测试命令、验证环境 |
两种进入方式
Docker 提供两种进入容器的命令:
| 命令 | 推荐程度 | 特点 |
|---|---|---|
docker exec |
✅ 推荐 | 启动新进程,退出不影响容器 |
docker attach |
⚠️ 谨慎使用 | 附加到主进程,退出可能停止容器 |
docker exec(推荐)
基本用法
# 进入容器并启动交互式 shell
$ docker exec -it 容器名 /bin/bash
# 或使用 sh(适用于 Alpine 等精简镜像)
$ docker exec -it 容器名 /bin/sh
参数说明
| 参数 | 作用 |
|---|---|
-i |
保持标准输入打开(interactive) |
-t |
分配伪终端(TTY) |
-it |
两者组合,获得完整交互体验 |
-u |
指定用户(如 -u root) |
-w |
指定工作目录 |
-e |
设置环境变量 |
示例
# 启动一个后台容器
$ docker run -dit --name myubuntu ubuntu
69d137adef7a...
# 进入容器(交互式 shell)
$ docker exec -it myubuntu bash
root@69d137adef7a:/# ls
bin boot dev etc home lib ...
root@69d137adef7a:/# exit
# 容器仍在运行!
$ docker ps
CONTAINER ID IMAGE STATUS NAMES
69d137adef7a ubuntu Up 2 minutes myubuntu
执行单条命令
不进入交互模式,直接执行命令:
# 查看容器内进程
$ docker exec myubuntu ps aux
# 查看配置文件
$ docker exec myubuntu cat /etc/nginx/nginx.conf
# 以 root 用户执行
$ docker exec -u root myubuntu apt update
只用 -i 不用 -t 的区别
# 只用 -i:可以执行命令,但没有提示符
$ docker exec -i myubuntu bash
ls # 输入命令
bin # 输出结果
boot
dev
...
# 用 -it:有完整的终端体验
$ docker exec -it myubuntu bash
root@69d137adef7a:/# # 有提示符
💡 通常使用
-it组合。只有在脚本中需要通过管道传入命令时才只用-i。
docker attach(谨慎使用)
基本用法
$ docker attach 容器名
工作原理
attach 会附加到容器的主进程(PID 1)的标准输入输出:
┌─────────────────────────────────────────┐
│ 容器 │
│ ┌─────────────────────────────────┐ │
│ │ PID 1: /bin/bash (主进程) │◄───┼─── docker attach 附加到这里
│ │ └─ 你的输入直接发送到主进程 │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
示例
# 启动容器
$ docker run -dit --name myubuntu ubuntu
243c32535da7...
# 附加到容器
$ docker attach myubuntu
root@243c32535da7:/#
⚠️ 重要警告
从 attach 会话中输入 exit 或按 Ctrl+D 会导致容器停止!
$ docker attach myubuntu
root@243c32535da7:/# exit # 这会停止容器!
$ docker ps
CONTAINER ID IMAGE STATUS NAMES
243c32535da7 ubuntu Exited (0) 2 seconds ago myubuntu
原因:attach 附加到主进程,退出主进程就等于退出容器。
安全退出 attach
使用 Ctrl+P 然后 Ctrl+Q 可以从 attach 会话中分离,而不停止容器:
$ docker attach myubuntu
root@243c32535da7:/#
# 按 Ctrl+P 然后 Ctrl+Q
read escape sequence
$ docker ps # 容器仍在运行
CONTAINER ID IMAGE STATUS NAMES
243c32535da7 ubuntu Up 5 minutes myubuntu
exec vs attach 对比
| 特性 | docker exec | docker attach |
|---|---|---|
| 工作方式 | 在容器内启动新进程 | 附加到主进程 |
| 退出影响 | 不影响容器 | 可能停止容器 |
| 多终端 | 可以开多个 | 共享同一个会话 |
| 适用场景 | 调试、临时操作 | 查看主进程输出 |
| 推荐程度 | ✅ 推荐 | ⚠️ 特殊场景使用 |
docker exec docker attach
┌─────────────────────┐ ┌─────────────────────┐
│ 容器 │ │ 容器 │
│ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ PID 1: nginx │ │ │ │ PID 1: bash │◄─┼── 附加到主进程
│ ├───────────────┤ │ │ └───────────────┘ │
│ │ PID 50: bash │◄─┼── 新进程 │ │
│ └───────────────┘ │ │ │
└─────────────────────┘ └─────────────────────┘
退出 bash 不影响 nginx 退出 bash 容器停止
最佳实践
1. 首选 docker exec
# 进入容器调试
$ docker exec -it myapp bash
# 查看日志
$ docker exec myapp tail -f /var/log/app.log
# 执行数据库迁移
$ docker exec myapp python manage.py migrate
2. 生产环境避免进入容器
笔者建议:生产环境应尽量避免进入容器直接操作,而是通过:
- 日志系统查看日志(如
docker logs或集中式日志) - 监控系统查看状态
- 重新部署而非手动修改
3. 无 shell 镜像的处理
某些精简镜像(如基于 scratch 或 distroless)没有 shell:
# 这会失败
$ docker exec -it myapp bash
OCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found
# 解决方案:使用调试容器(Docker Desktop 或 Kubernetes debug)
$ docker debug myapp
常见问题
Q: exec 进入后看不到其他终端的操作
这是正常的。exec 启动的是独立进程,多个 exec 会话互不影响。
Q: 容器没有 bash
尝试使用 sh:
$ docker exec -it myapp /bin/sh
Q: 需要 root 权限
$ docker exec -u root -it myapp bash
本章小结
| 需求 | 推荐命令 |
|---|---|
| 进入容器调试 | docker exec -it 容器名 bash |
| 执行单条命令 | docker exec 容器名 命令 |
| 查看主进程输出 | docker attach 容器名(慎用) |