コンテナのイメージをスクラッチで作り -t オプションの動きを確認する



# 0.実験の目的

docker run で使用できる `-t` オプションは「疑似 tty の割り当て」をするオプションとされている。
<a href="https://docs.docker.jp/engine/reference/run.html#foreground" target=_blank>Docker run リファレンス — Docker-docs-ja 20.10 ドキュメント</a>


`-t` を付けた時に、`pts(疑似端末/pseudo-tty)` を開いてる bash は、イメージの Dockerfile 内のCMD[`/bin/bash`]で実行している`bash`である。という事を確認するのがこの実験の目的である。

つまり`-t`オプション自身が、`pts` を作成し、さらにそれを使用する `bash`も作るという2つの作業を実行しているわけで**ない**事を確認する。

言い換えると、どんなイメージでも `-t` (現実的には `-it` )だけで、コンテナに接続できるわけではない事を確認する。

ここでは、scratch から `CMD ["/bin/bash"]` 入りと CMD 無しのイメージを作って、`CMD ["/bin/bash"]` の影響を観察する。

# 1. bash入りのイメージと bash 無しのイメージを作る

`scratch` のイメージには何も入ってないので、`bash`が使っているライブラリと、`bash`自身をコピーする`Dockerfile`を作る

```
$ which bash   # bash の正確なパス
/bin/bash
$ ldd /bin/bash　　# 依存関係の調査
        linux-vdso.so.1 (0x00007ffca48e1000)
        libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fa3397df000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa3395db000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa3391ea000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa339d23000)
$
```

一番、はじめの`linux-vdso.so.1` は、find でも見つからない。これは特殊なライブラリで、カーネルに埋め込まれているそうなので、コピーの必要がなさそう。

**小ネタ**
このライブラリの名前`linux-vdso.so`をURLバーに入れると猫画像が出た。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99425/34eb6550-6114-498d-fc5b-00f9024e8e34.png)
(いつマルウェアのサイトに変わるかもしれないので直リンクは省略)


Dockerfile では、COPY元のファイルを指定するには、Dockerfile の場所からの相対パスを書ないといけない。相対パスを書くのが面倒なので、カレントディレクトリに必要なものをコピーする。

```
$ cp /bin/bash .
$ cp /lib/x86_64-linux-gnu/libtinfo.so.5 .
$ cp /lib/x86_64-linux-gnu/libdl.so.2 .
$ cp /lib/x86_64-linux-gnu/libc.so.6 . 
$ cp /lib64/ld-linux-x86-64.so.2 .
$ ls -ltr
total 3432
-rwxrwxrwx 1 yuhki yuhki  170784 Dec 27 16:05 libtinfo.so.5
-rwxrwxrwx 1 yuhki yuhki   14560 Dec 27 16:05 libdl.so.2
-rwxrwxrwx 1 yuhki yuhki  179152 Dec 27 16:05 ld-linux-x86-64.so.2
-rwxrwxrwx 1 yuhki yuhki 1113504 Dec 27 16:06 bash
-rwxrwxrwx 1 yuhki yuhki     248 Dec 27 16:11 Dockerfile1
-rwxrwxrwx 1 yuhki yuhki     266 Dec 27 16:12 Dockerfile2
-rwxrwxrwx 1 yuhki yuhki 2030928 Dec 27 16:13 libc.so.6
$
```

以下の2つの`Dockerfile`を作る。

**Dockerfile1 (CMD 無し)**

```Dockerfile1  
FROM scratch
COPY ./bash /bin/bash
COPY ./libtinfo.so.5 /lib/x86_64-linux-gnu/libtinfo.so.5
COPY ./libdl.so.2 /lib/x86_64-linux-gnu/libdl.so.2
COPY ./libc.so.6 /lib/x86_64-linux-gnu/libc.so.6
COPY ./ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
```

**Dockerfile2 (CMD で bash 実行)**

```Dockerfile2
FROM scratch
COPY ./bash /bin/bash
COPY ./libtinfo.so.5 /lib/x86_64-linux-gnu/libtinfo.so.5
COPY ./libdl.so.2 /lib/x86_64-linux-gnu/libdl.so.2
COPY ./libc.so.6 /lib/x86_64-linux-gnu/libc.so.6
COPY ./ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
CMD ["/bin/bash"]
```

**Dockerfile1のbuild**

```
$ docker build  -t my-scratch1 -f Dockerfile1 .
```

**Dockerfile2のbuild**

```
$ docker build  -t my-scratch2 -f Dockerfile2 .
```

**buildしたイメージの確認**

```
$ docker images | grep scratch
my-scratch1                                               latest    f4b3f18c5757   3 hours ago     3.51MB
my-scratch2                                               latest    bd8539ac3f76   3 hours ago     3.51MB
$ 
```

# 2.ビルドしたイメージを実行する

## 2.1.CMD["/bin/bash"]無しのイメージからコンテナを生成

```
$ docker run -itd --name my-container2 my-scratch1
docker: Error response from daemon: No command specified.
See 'docker run --help'.
$ 
```

実行できない。`No command specified` というエラーになる。
`-t` オプションは付けているが、これは`pseudo-tty`を生成するだけで、それを使うシェルが無いとそもそも起動できない事がわかる。

今度は、`docker run`時に、引数で`/bin/bash`を起動してみる。

```
$ docker run -itd --name my-container1 my-scratch1 /bin/bash
1983d63b34a9a584f7cb1922a1fa6686690342f99a658449b794a22adb552f0c
$ docker ps
CONTAINER ID   IMAGE         COMMAND       CREATED         STATUS         PORTS     NAMES
1983d63b34a9   my-scratch1   "/bin/bash"   4 seconds ago   Up 3 seconds             my-container1
$
```

今度は、コンテナは終了しない。

## 2.2. CMD[/bin/bash]を指定したイメージからコンテナを生成

```
$ docker run -itd --name my-container2 my-scratch2
5e265705f95f1601d5b3bf3ec8b457a682f299abd1dabed9d25f19f1a3ba942a
$ docker ps
CONTAINER ID   IMAGE         COMMAND       CREATED         STATUS         PORTS     NAMES
5e265705f95f   my-scratch2   "/bin/bash"   3 seconds ago   Up 2 seconds             my-container2
$
```

起動できる。

敢えて `/bin/bash` を起動しないくても、コンテナは終了しない。CMD で指定した `/bin/bash` が効いているのがわかる。

以上の事から `pts(疑似端末/pseudo-tty)` を使う `bash`がいて、はじめて`-t`オプションが意味を持ってくる事がわかった。