Problem entry · machine-readable · 编码代理与终端

docker exec 报 the input device is not a TTY / container is not running / executable file not found

本页嵌入 #trove-entity JSON(本条目全量结构化数据);全库数据见 /agent/trove.json。

元数据

iddocker-exec-tty收录2026-08-29
问题域编码代理与终端主题分组容器与 WSL
适用工具docker · 外部工具

症状

脚本、CI(Jenkins/GitHub Actions)或管道里跑 `docker exec -it ...` / `docker compose exec ...` 报:

```

the input device is not a TTY

```

同族症状:`docker exec` 进已停止容器报 `Error response from daemon: container <id> is not running`;

对 alpine 等精简镜像跑 `docker exec <c> bash` 报 `exec: "bash": executable file not found in $PATH`。

特征:交互式命令在**没有终端**的环境里执行;手动在终端里跑同一命令却正常——所以总被当成玄学。

原因

`-t`(--tty)要求分配一个 TTY 伪终端,脚本/CI 的标准输入不是终端,docker CLI 直接拒绝启动;

`docker compose exec` 默认带 -t,所以 compose 场景更容易踩。

解法

1. **非交互命令去掉 `-t`**:`docker exec <c> sh -c "命令"`;需要 stdin 管道时只留 `-i`:

`echo 数据 | docker exec -i <c> sh -c "cat"`(实测均可)。

2. **compose 场景**:`docker compose exec -T <service> 命令`(-T = 禁用 TTY);

旧版 v1 可加 `export COMPOSE_INTERACTIVE_NO_CLI=1`,但新版本以 `-T` 为准。

3. **判断 TTY**:脚本里可用 `[ -t 0 ]` 检测 stdin 是否是终端,条件决定是否加 `-t`。

4. **容器没在跑**:先 `docker start <c>` 或 `docker logs <c>` 看为什么退出(exit code 1 的容器先排查启动失败原因,别盲目 start)。

5. **没有目标命令**:先 `docker exec <c> ls /bin /usr/bin` 看镜像里有什么;alpine 用 `sh`,要 bash 就换 ubuntu/debian 镜像,或 `docker exec <c> sh -c "命令"`。

6. 交互式进入容器(真终端):`docker exec -it <c> sh`,保持 -it 不变。

验证证据

- 本地实测(2026-08-29,WSL Ubuntu,docker 29.1.3,alpine:3.20):

- 复现:`docker exec -it <c> sh </dev/null`(非 TTY)→ `the input device is not a TTY`(exit 1),与 compose#7306 同款;

- 修复 1:`echo hello | docker exec -i <c> sh -c "cat"` → hello(exit 0);

- 修复 2:`docker exec <c> sh -c "echo noninteractive-ok"` → 正常(exit 0);

- 形态 2:容器 stop 后 `docker exec <c> echo x` → `container ... is not running`(exit 1);

- 形态 3:`docker exec <c> bash -c ...` → `exec: "bash": executable file not found in $PATH`(exit 127);

- 清理:容器删除无残留。

- 实测复现日志(2026-08-29)

来源与证据

素材来源:https://github.com/docker/compose/issues/7306

验证证据:Evidence details kept locally (2026-08-29)