おもなオプション

下記は docker exec を例に説明していますが、d、t、i オプションは docker run にも当てはまります。

-d, –detach=false デタッチド・モード: コマンドをバックグラウンドで実行
-i, –interactive=false アタッチしていなくても STDIN をオープンにし続ける
-t, –tty=false 疑似ターミナル (pseudo-TTY) の割り当て

http://docs.docker.jp/engine/reference/commandline/exec.html

※ tty:teletypewriter(仮想コンソール)

概要

ubuntu:24.04 を例に挙動をまとめます。

  1. Docker コンテナはルートプロセス(PID:1)が終了されたらコンテナを終了します
  2. docker run で t オプションを付与することで PID:1 の bash に擬似 tty(pts/1:pseudo-terminal)が接続されて、プロセスが稼働し続けるので(ルートプロセスが終了しないので)コンテナは終了しません。
  3. docker run で i オプションを付与することでアタッチしていなくても標準入力(STDIN)がオープンなままになります(コンテナ内で入力が可能になります)

※ 例えば httpd は CMD でデーモンを起動します。PID:1 に httpd デーモンを割り当てるので t オプションを付与しなくてもコンテナは終了しません。

ubuntu:24.04 を例にして docker run のオプションによる挙動の違いを確認します。

it オプションを付与しない

オプションを付与しない場合は、コンテナが直ちに終了します。

docker run ubuntu:24.04
docker ps --all

# コンテナのSTATUSはExited
# CONTAINER ID   IMAGE     COMMAND   CREATED         STATUS                     PORTS     NAMES
# 7b7ca3ef3875   ubuntu    "bash"    5 seconds ago   Exited (0) 4 seconds ago             competent_keller

t オプションを付与する

t オプションを付与した場合は、コンテナは終了しません。
挙動の確認で t オプションのみを付与しています。現実的にiオプションを付与しないで、tオプションのみを付与するユースケースはあまりなさそうです。

# 分かりやすさのためにデタッチする
docker run -dt ubuntu:24.04
docker ps --all

# コンテナの STATUS は Up
# CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
# e8fe0d1b6fd7   ubuntu    "bash"    27 seconds ago   Up 26 seconds             strange_shamir

Docker Compose では tty プロパティを true します。

参考 デタッチをしない場合

参考までにデタッチしない場合を記載します。

# デタッチしない場合は疑似 tty が立ち上がった状態になる
# iオプションを指定しないので、入力はコンテナに渡らない
$ docker run -t ubuntu:24.04
root@cbfb393cff94:/# echo HELLO
// 応答がない
// 入力を受け付けないので exit や Ctrl + C なども受け付けない

i オプションを付与する

i オプションを付与します(分かりやすさのために t オプションも付与します)。
疑似 tty が入力を受け付ける。

$ docker run -it ubuntu:24.04
root@299f5cfdbbe0:/# echo 'Hello' # i オプションによって標準入力がオープンされている
Hello

Docker Composeでは stdin_open: true とします。

it オプションを付与

ホストの tty を確認します。

$ tty
/dev/pts/0

ubuntu:24.04を起動する

$ sudo docker run -itd --name ubuntu-sample ubuntu:24.04

コンテナ ubuntu-sample にログインしてプロセスを確認します。
2022年05月29日時点の Docker 公式 ubuntu:24.04 は ps コマンドがないのでインストールします(apt install -y procps)。

$ sudo docker exec -it ubuntu-sample /bin/bash
root@f839023fec94:/# ps auxf
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           8  0.0  0.6   4628  3184 pts/1    Ss   01:34   0:00 /bin/bash
root         224  0.0  0.3   7060  1624 pts/1    R+   01:34   0:00  \_ ps auxf
root           1  0.0  0.4   4492  2232 pts/0    Ss+  01:33   0:00 bash
  • PID:1 のbashの TTY はコンテナ起動時に t オプションで接続された pts/0
  • PID:8 の/bin/bashの TTY は pts/1 が接続

意味はないが参考までに httpd:latest を t オプションを付与して起動してみる。

$ sudo docker run -td -p 8000:80 --name httpd-sample httpd

コンテナ httpd-sample にログインしてプロセスを確認します。 2022年05月29日時点の Docker 公式 httpd:latest は ps コマンドがないのでインストールします(apt install -y procps)。

$ sudo docker exec -it httpd-sample /bin/bash
root@57a67d981f30:/usr/local/apache2# ps auxf
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          91  0.0  0.7   4484  3520 pts/1    Ss   01:56   0:00 /bin/bash
root         427  0.0  0.6   6700  2872 pts/1    R+   02:00   0:00  \_ ps auxf
root           1  0.0  0.5   5936  2820 pts/0    Ss+  01:56   0:00 httpd -DFOREGROUND
www-data       7  0.0  0.5 751860  2436 pts/0    Sl+  01:56   0:00 httpd -DFOREGROUND
www-data       8  0.0  0.5 751860  2436 pts/0    Sl+  01:56   0:00 httpd -DFOREGROUND
www-data       9  0.0  0.5 751860  2436 pts/0    Sl+  01:56   0:00 httpd -DFOREGROUND
  • PID:1 のhttpd -DFOREGROUND の TTY にはコンテナ起動時にtオプションによって作成された pts/0 が接続
  • PID:91の /bin/bash のTTYは pts/1 が接続

ちなみに起動時にtオプションを指定しないで httpd:latest を起動した場合は httpd -DFOREGROUND は ? になります 通常デーモンは TTY が接続されない。その場合には ps コマンドの TTY は ? になります。 以下に t オプションを指定しない(こちらが通常)場合の例を示す。

root@08c958e0c19b:/usr/local/apache2# ps auxf
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          91  0.0  0.6   3968  2904 pts/0    Ss   02:03   0:00 /bin/bash
root         422  0.0  0.6   6700  2940 pts/0    R+   02:03   0:00  \_ ps auxf
root           1  0.0  0.5   5936  2848 ?        Ss   02:02   0:00 httpd -DFOREGROUND
www-data       7  0.0  0.5 751860  2396 ?        Sl   02:03   0:00 httpd -DFOREGROUND
www-data       8  0.0  0.5 751860  2396 ?        Sl   02:03   0:00 httpd -DFOREGROUND
www-data       9  0.0  0.5 751860  2396 ?        Sl   02:03   0:00 httpd -DFOREGROUND

Docker Compose

  • t: tty: true
  • i: stdin_open: true

docker attach と docker exec

docker attach と docker exec の違いでtオプションを理解を深めます。
ubuntu:24.04を例に挙動を確認する。

$ docker run -dit ubuntu:24.04
44d6eef27255......

docker attach

$ docker attach 44d6eef2725
root@44d6eef27255:/# ps auxf
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.2  0.1   4488  3732 pts/0    Ss   06:03   0:00 bash
root         8  0.0  0.0   7056  1608 pts/0    R+   06:03   0:00 ps aux
root@44d6eef27255:/# exit
exit

上記のように PID:1 の bash に標準入出力が接続されます。
よって exit コマンドを発行した場合は、PID:1 のプロセス(ルートプロセス)が終了するのでコンテナも終了します。

$ docker ps --all

# コンテナSTATUSはExited
CONTAINER ID   IMAGE     COMMAND   CREATED              STATUS                     PORTS     NAMES
44d6eef27255   ubuntu    "bash"    About a minute ago   Exited (0) 9 seconds ago             objective_elgamal

docker exec

$ docker exec -it 44d6eef27255 /bin/bash
root@44d6eef27255:/# ps auxf
# 標準入出力はPID:16の /bin/bash に接続されている。
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root        16  0.6  0.1   4488  3720 pts/1    Ss   06:11   0:00 /bin/bash
root        24  0.0  0.0   7056  1556 pts/1    R+   06:11   0:00  \_ ps auxf
root         1  0.0  0.1   4488  3520 pts/0    Ss+  06:10   0:00 bash
root@44d6eef27255:/# exit
exit

上記のように標準入出力は PID:16 の /bin/bash に接続されます。
exit コマンドを発行した場合、PID:16 のプロセスが終了して、PID:1 のプロセス(ルートプロセス)は終了しないのでコンテナは稼働したままになります。

※ i オプションを付与しないと PID:16 /bin/bash(pts/1)に入力できません。

$ docker ps --all
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS         PORTS     NAMES
44d6eef27255   ubuntu    "bash"    10 minutes ago   Up 3 minutes             objective_elgamal

httpd

httpd は PID:1 のプロセスで httpd デーモンが稼働します(httpd -DFOREGROUND)。
よってオプションを付与しなくてもコンテナは終了しません。

$ docker run -d httpd:latest
bb5c45b3c386......
$ docker ps --all
CONTAINER ID   IMAGE     COMMAND              CREATED              STATUS              PORTS     NAMES
bb5c45b3c386   httpd     "httpd-foreground"   About a minute ago   Up About a minute   80/tcp    competent_curie

docker attach

httpd:latest の PID:1 のプロセスは httpd デーモンが稼働します。 よって以下はエラーにはなりませんが、bash に接続されるわけではありまえん。

$ docker attach bb5c45b3c386

docker exec

docker exec でログインします。
ps を使用するために procpsをインストールします。

$ docker exec -it bb5c45b3c386 /bin/bash
root@bb5c45b3c386:/usr/local/apache2# apt -y update && apt install -y procps
.....
.....
.....
root@bb5c45b3c386:/usr/local/apache# ps auxf
ps auxf
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root        92  0.0  0.1   3964  3300 pts/0    Ss   06:54   0:00 /bin/bash
root       423  0.0  0.1   6696  3040 pts/0    R+   06:56   0:00  \_ ps auxf
root         1  0.0  0.2   5932  4524 ?        Ss   06:54   0:00 httpd -DFOREGROUND
www-data     8  0.0  0.1 1210608 3492 ?        Sl   06:54   0:00 httpd -DFOREGROUND
www-data     9  0.0  0.1 1210608 3560 ?        Sl   06:54   0:00 httpd -DFOREGROUND
www-data    10  0.0  0.1 1210608 3492 ?        Sl   06:54   0:00 httpd -DFOREGROUND
root@bb5c45b3c386:/usr/local/apache# exit
$ docker ps --all
CONTAINER ID   IMAGE     COMMAND              CREATED         STATUS         PORTS     NAMES
bb5c45b3c386   httpd     "httpd-foreground"   3 minutes ago   Up 3 minutes   80/tcp    youthful_rubin

Ref