パイプではまらないためにdockerコマンド実行時の「-it」オプションの挙動を確認してみた
はじめに
docker run
コマンドや docker exec
コマンドを実行する際に -i
オプションと -t
オプションを付与することが多いですが、
理解をしていないとパイプとつなぐ際に思わぬ挙動をするので整理しました。
検証環境
$ bash -version | head -n 1
GNU bash, バージョン 5.0.7(1)-release (x86_64-apple-darwin18.5.0)
$ docker --version
Docker version 18.09.2, build 6247962
各種オプションの有無での挙動の違い
-i
オプション有り、 -t
オプション有り
まずは -it
オプションつきでDockerコンテナを起動し bash
を起動してみます。
接続したコンテナ内でLinuxコマンドを実行でき、結果をターミナルで確認できます。
$ docker run -it ubuntu:19.10 bash
root@5ba28223ab82:/# ls
bin dev home lib32 libx32 mnt proc run srv tmp var
boot etc lib lib64 media opt root sbin sys usr
root@5ba28223ab82:/# echo test
test
-i
オプション無し、 -t
オプション無し
両方のオプションを外した場合はどうでしょう?
$ docker run ubuntu:19.10 bash
コンテナは直ちに終了してしまいます。
-i
オプション無し、 -t
オプション有り
今度は -t
オプションだけ付与して実行してみます。
$ docker run -t ubuntu:19.10 bash
root@58ad0e36e274:/# ls
先ほどと異なり、インタラクティブなBashが起動できました。-t
オプションについてヘルプを見てみます。
$ docker run --help | grep '\-t'
--add-host list Add a custom host-to-IP mapping (host:ip)
--cpu-rt-period int Limit CPU real-time period in microseconds
--cpu-rt-runtime int Limit CPU real-time runtime in microseconds
--disable-content-trust Skip image verification (default true)
--health-timeout duration Maximum time to allow one check to run (ms|s|m|h) (default 0s)
--stop-timeout int Timeout (in seconds) to stop a container
--tmpfs list Mount a tmpfs directory
-t, --tty Allocate a pseudo-TTY
-t
はtty(擬似端末)をコンテナに割り当てるためのオプションです。
これによりBashがインタラクティブモードで起動することとなります。プロンプトも表示されていますね。
ここで ls
と入力し、Enterキーを押してみます。ls
の結果が何も出力されないはずです。exit
もできなくなりました。
こうなると CTRL+C
で抜けるしかありません。
-i
オプション有り、 -t
オプション無し
今度は -i
オプション付きだけを付与してみます。
$ docker run -i ubuntu:19.10 bash
何も表示されませんが、ここで ls
と入力してみます。
ls
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
プロンプトがないのでわかりにくいですが、一番上の ls
は自分で入力したコマンドです。-i
オプションがあって初めて、コマンドの入力が可能となります。
逆に -i
オプションだけでコンテナに対する操作はできます(-t
は必要ない)。
ちなみに、以下のように vim
をインストールして起動することもできました。
$ apt-get update -y && apt-get install vim -y
$ vim
パイプと組み合わせてみる(標準入力)
単体でのコンテナ起動の挙動は確認できました。
今度はパイプと組み合わせた場合の挙動について確認してみます。
echo ls | ...
というコマンド形式で、コンテナ起動時に標準入力を受け取るようにしてみます。
-i
オプション有り、 -t
オプション有り
両方のオプションを付与した場合は、正常に動作しません。
$ echo ls | docker run -it ubuntu:19.10 bash
the input device is not a TTY
入力デバイスがTTYでないので -t
を付与してはいけないようです。
-i
オプション無し、 -t
オプション無し
以下のコマンドでは何も出力されません。
コンテナが標準入力を受け付けないためです。
$ echo ls | docker run ubuntu:19.10 bash
以下のコマンドを実行したのと同じです。
$ echo ls; docker run ubuntu:19.10 bash
-i
オプション無し、 -t
オプション有り
インタラクティブシェルが起動しますが、標準入力を受け取るようにしていないため何もできません。
$ echo ls | docker run -t ubuntu:19.10 bash
root@b60730972a07:/#
以下のコマンドを実行したのと同じです。
$ echo ls; docker run -t ubuntu:19.10 bash
-i
オプション有り、 -t
オプション無し
正しく標準入力を受け取り、 ls
コマンドが実行されます。
実行後、コンテナは終了します。
$ echo ls | docker run -i ubuntu:19.10 bash
bin
boot
dev
etc
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
パイプと組み合わせてみる(標準出力)
-i
オプション有り、 -t
オプション有り
何故か、おかしなインデントが出力されてしまいます。
$ docker run -it ubuntu:19.10 echo '{ "x": 1 }' | jq .
{
"x": 1
}
-i
オプション無し、 -t
オプション無し
正常に動作。
$ docker run ubuntu:19.10 echo '{ "x": 1 }' | jq .
{
"x": 1
}
-i
オプション無し、 -t
オプション有り
正常に動作。
$ docker run -i ubuntu:19.10 echo '{ "x": 1 }' | jq .
{
"x": 1
}
-i
オプション有り、 -t
オプション無し
正常に動作。
$ docker run -t ubuntu:19.10 echo '{ "x": 1 }' | jq .
{
"x": 1
}
フィルダリングを行うようなコンテナ起動を行う場合
標準入力を受け取り、標準出力を送り込むコンテナ起動用のコマンドは以下のようになります。
$ echo 123 | docker run -i ubuntu:19.10 sed 's/2/---/' | sed 's/3/+++/'
1---+++
ひとこと
コンテナにフィルダリング処理をさせるという発想はどうなんでしょうね。
問題があるのかないのか。
ディスカッション
コメント一覧
まだ、コメントがありません