📚

docker で "the input device is not a TTY" のエラーが出ないようにする

2024/01/13に公開

docker で "the input device is not a TTY" のエラーが出ないようにする

概略

docker run するときに、cron、CI、nohup などで実行した場合など、標準入力デバイスが TTY ではないときに docker run -it を指定して実行すると、"the input device is not a TTY" のエラーになる。

シェルから実行する場合、Control+C で実行を止めることができるように -it を指定したいが、バックグラウンド処理としても実行したい場合、困る。標準入力デバイスが TTYか判定して -it を指定するかしないかを切り替える。

エラーの例

NG な場合の例

$ echo "" | docker run -it hello-world
the input device is not a TTY
$ nohup docker run -it hello-world
$ cat nohup.out
the input device is not a TTY

OK な場合の例

$ docker run -it hello-world

Hello from Docker!
    ... 以下略 ...

判定

以下のようなシェルスクリプトを組む。

#!/bin/bash

SELF=$$
ls /proc/$SELF/fd/0 -l | grep /dev/pts > /dev/null
if [ $? -eq 0 ]; then
        echo "input device is TTY device"
        OPTION=-it
else
        echo "input device is non TTY"
        OPTION=
fi
docker run $OPTION hello-world

$$ はシェルスクリプト自身の PID を表す。
/proc/PID/fd/0 で指定した PID のプロセスの標準入力の実体を確認できる。

ターミナルから実行された場合、実体が /dev/pts/0 などになっている。
ターミナル以外から実行された場合やパイプで実行された場合などは /dev/pts を含まない。

grep /dev/pts でマッチするかどうかで判定することで、docker run -it を実行したとき the input device is not a TTY が発生する条件であるか事前に判定できる。

Discussion