Files
docker_practice/05_container/attach_exec.md

7.2 KiB
Raw Blame History

进入容器

为什么需要进入容器

使用 -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 镜像的处理

某些精简镜像(如基于 scratchdistroless)没有 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 容器名(慎用)

延伸阅读