普段なんとなく、あまり理解せず使っているdockerに関して少し調べてみた的な内容になっています。
調べながらまとめた内容になるので、間違っているところなどあればコメントなどでご指摘いただけるとありがたいです!
普段dockerでコンテナに入りshellを操作したい時に、
docker exec -it コンテナ名 bash
のようなコマンドをよく使います。
今回はこのコマンドに関して調べた内容をまとめました。
docker exec
docker exec
は docker exec のリファレンス によると、
使い方: docker exec [オプション] コンテナ コマンド [引数...]
実行中のコンテナでコマンドを実行
とあるので、下記コマンドの場合は
docker exec -it コンテナ名 bash
-it
がオプション、 bash
がコマンドとなります。
なので上記コマンドは、指定したコンテナで bash を実行するコマンド ということになります。
本題
指定したコンテナでbashを実行するだけでは、普段のコンテナに入りshellを操作することはできないので、その部分を理解する為に-it
オプションが何をしているか知る必要がある。
それぞれ docker exec の リファレンス によると
-i, --interactive=false アタッチしていなくても STDIN をオープンにし続ける
-t, --tty=false 疑似ターミナル (pseudo-TTY) の割り当て
よ、よくわからない、、、
1つずつ確認していきます。
まずはコンテナを立ち上げたいので、下記コマンドを入力します。
docker run --name php-test php:apache
docker run コマンドはイメージをもとにコンテナを立ち上げます。
上記コマンドでは、php:apache
というイメージをもとに、php-test
という名前コンテナを立ち上げます。
まずはこのコンテナの中に入ってshellを操作してみたいと思います。
docker exec -it php-test bash
上記コマンドを打つと、コンテナのshellを操作できるようになります
root@コンテナID:/var/www/html# ps a
PID TTY STAT TIME COMMAND
23 pts/0 Ss 0:00 bash
31 pts/0 R+ 0:00 ps a
ps a
コマンドを打ち込み、現在のプロセスを表示すると、PID23でbash
、それとPID31で先程打ち込んだps a
コマンドのプロセスが表示されています。
この状態を維持したまま、新たに別のターミナルを起動し同じように下記コマンドでコンテナに入り、プロセスを表示します。
docker exec -it php-test bash
root@コンテナID:/var/www/html# ps a
PID TTY STAT TIME COMMAND
23 pts/0 Ss+ 0:00 bash
32 pts/1 Ss 0:00 bash
38 pts/1 R+ 0:00 ps a
確認すると bash
コマンドのプロセスが1つ増えています。
ここで注目する部分は、TTYの項目になります。
前述したdocker exec
のオプション -t
には下記のような記述がありました。
-t, --tty=false 疑似ターミナル (pseudo-TTY) の割り当て
pseudo は擬似という意味。
tty は wikipediaより
ttyとは、標準入出力となっている端末デバイス(制御端末、controlling terminal)の名前を表示するUnix系のコマンドである。元来ttyとはteletypewriter(テレタイプライター)のことを指す。
例えば、SSH などを経由し、Unix98 PTY の擬似端末に接続している状況で tty を実行すると、以下のような表示が返される。
% tty
/dev/pts/1
わかりそうでわからない(知識不足)。
わからないなりに、docker exec -it php-test bash
をするたびに、TTYの項目、pts/0
の数値部分が増えていくので、新たにttyが割り当てられていることがわかる。
おそらく-t
コマンドをつけないとttyが割り当てられないのだろうと思い、
3つ目のターミナルで-i
のみでコマンドを実行すると、
docker exec -i php-test bash
、、、何も起きない、、、
おそらくttyが割り当てられていない状態だが、-i
オプションが効いているのでこの画面で入力したコマンドは、コンテナがSTDIN(標準入力)を開き続けているので、そこと繋がっていると思われます。(後述)
なんの反応もない画面で3回くらいbash
打ち込んだ後、2つ目のターミナルでps a
するとPIDが進んでいるので、bashのプロセス自体は作られているようでした。
次は-t
のみをつけてコマンドを実行してみます。
3つ目のターミナルで、control + c
で画面をもとに戻した後下記コマンドを実行。
docker exec -t php-test bash
すると、見覚えのある画面になりますが、ps a
はもちろんどのコマンドを打っても何も反応しません。
リファレンスにあったオプションの内容を再確認してみます。
-i, --interactive=false アタッチしていなくても STDIN をオープンにし続ける
アタッチしていなくても という部分から、おそらくdocker attach
コマンドなどでコンテナにアタッチする時は、STDINがオープンの状態になっているが、普段はコンテナのSTDINがオープンになっていない状態だろうということがわかります。
STDINをオープンにし続けるという部分から、-i
を指定することで、コンテナにアタッチしていない状態でもSTDINをオープンにし続ける、標準入力を受け付ける状態にする、ということがわかります。
確認の為、2つ目のターミナルでps a
を実行すると、
root@5ee2e1cf4cb5:/var/www/html# ps a
PID TTY STAT TIME COMMAND
23 pts/0 Ss+ 0:00 bash
32 pts/1 Ss 0:00 bash
56 pts/2 Ss+ 0:00 bash
64 pts/1 R+ 0:00 ps a
pts/2
が追加されているので、 -t
をつけると、擬似ターミナルが割り当てられるが、-i
がないとコマンドの実行などができないということがわかった。
まとめ
docker exec -it コンテナ名 bash
などで、コンテナ内でshellの操作をしたい時は、-i -t
の2つのオプションの指定が必要。
-t
だけだと、擬似ターミナルが割り当てられて、shell画面が表示されるが、標準入力と接続されていないので、コマンドの実行はできない。
-i
だけだと、標準入力とつながるが、擬似ターミナルが割り当てられないので、コマンドを実行しても何が起こっているかわからない状態になってしまう。