docker runの[ i, t, d ]オプションの意味を調べた

# はじめに

Dockerについて初心者の自分が
理解するのに難しかった部分を少しまとめます。
特に、コマンドオプションのところが難しかったので
少しでも自分と同じようなDocker初心者の方の理解の助けになればと思います！(^^)
間違った部分がありましたら是非お教えください！m(_ _)m

#Dockerとは

これについては他にも沢山の記事があるので深く言及しませんが、
**プロセスをコンテナ化するための仮想化ソフトウェア**です。
Windowsの中に、Ubuntuも起動したい、そういった仮想化要望を叶えてくれます。

主に、**開発したものをデプロイする！**って時に役立つようです。
本番環境はLinux！でも自分のPCはWindows！な時に、
Windows上に、**「コンテナ」**という箱を作り、その箱の中にLinuxを立ち上げて開発をする感じ。
もう少し具体的な使い方は、
Webサーバー用コンテナ、データベース用コンテナなどを作って開発をして
本番環境にそのままえーいっ！って使い方なのかな？

複数人で開発する時に、
みんなの環境を合わせる意味でも便利なようです！

以下の記事が丁寧で分かりやすかったです。
>
・[Dockerとはどういったものなのか、めちゃくちゃ丁寧に説明してみる](https://qiita.com/SatoshiSobue/items/a612ebbb3a9242c09db5)
・[【連載】世界一わかりみが深いコンテナ &amp; Docker入門](https://tech-lab.sios.jp/archives/18811)

#Dockerの使い方
##Dockerのインストール
まずは、Docker自体をインストールする必要があります。

　　公式サイト : [https://docs.docker.com/get-docker/](https://docs.docker.com/get-docker/)

**こんなコンテナを作りたーい！**って頼めば、そんなコンテナを作ってくれて、
**コンテナ何個も作ったから管理してー！**って頼めば複数のコンテナを管理してくれるやつです。
（管理は頼まずとも基本勝手に良い感じにしてくれます）

Dockerをインストールしたら、
コマンドでDockerを操作することができるようになります。

```
docker ~~~~
```
みたいな感じでコマンドを打って、Dockerを操作します。

Linux以外？は、
「Docker Desktop For Windows/Mac」というGUIツールもありますね^^

##Docker Image

先ほど述べた、
**こんなコンテナ作りたーい**　とは
**こんなImageのコンテナ作りたーい**　ということで
具体的には
**Ubuntuが入ったコンテナを作りたーい**　というようなことです。

なので、**コンテナ**を作るために、まずは**「Image」**を手に入れる必要があります。
これを**「Docker Image」**と言います。

　　「　イメージ　→　コンテナ　」　≒　「　クラス　→　インスタンス　」

みたいな感じで考えれば、理解しやすいかもです。
Image群は基本的にここにあります。

　　Docker Hub : [https://hub.docker.com/](https://hub.docker.com/)

Docker Imageのリポジトリです。
GitHubのような感じと思えば良し。

ここからImageを取ってきて、（必要があれば自分でカスタマイズして）
コンテナを作っていきます。

```
docker pull someImage
```
でImageをローカルに取ってくる。

```
docker push someImage
```
でImageをサーバーにpushします。

既存のImageをカスタマイズして、自分でImageを作ることもできます。
**「Dockerfile」**というファイルにいろいろと設定を書いて

```
docker build -t imageName .    // ※Dockerfile が存在する階層にいる想定 
```
でImageを作成します。

##コンテナの作成・起動

Docker Imageを元に
実際のプロセスであるコンテナを作ります。

```
docker create --name containerName someImage
```

そして、プロセスを動かす。

```
docker start containerName/containerID
```

コンテナID（containerID）は
コンテナを作成した時に自動的に付けられます。

コンテナ名（containerName）も指定しなければ自動的に付けられますが、
[ --name ] オプションを使って、自分で管理しやすい名前を付けるのが良いと思います。


上記の、作成・起動という動作を一度に行ってくれるのが

```
docker run --name containerName someImage
```
です。

##コンテナの停止・削除
動いているコンテナを停止するのが

```
docker stop containerName 
```

そして、停止しているコンテナ自体を削除するのが

```
docker rm containerName 
```

動作中のコンテナを強制削除するには、

```
docker rm -f containerName 
```
として、[ -f ] オプションを使います。

---

全体的に
**「イメージ情報」を持ったクラス**から
**「実際のプロセス（コンテナ）」であるインスタンス**を作って
**Dockerが管理しているリストにコンテナを登録する**
みたいに考えれば自分は理解しやすかったです。

なので、
あくまでコンテナ自体はそれぞれ独立しています。
同じイメージから２つコンテナを作っても、それらはデータを共有してる訳ではないし、
コンテナを削除したら、そのコンテナで使っていたデータは基本的には消えます。
（データを永続化するには、Volume設定をする必要がある）

#Dockerコマンドのオプション
ここまでの内容は
様々な記事で書かれていて理解もしやすかったのですが、
自分が結構悩んだのがよく使うオプションの挙動？というか意味合い？でした。

自分の中でも、これはこう書きましょう的な
ある種のおまじないのようになっていたので
少し踏み込んで調べてみて、ちょっとだけわかった気がしたので書いてみます。

##[ -i ][ -t ]オプション

これらのオプションは

```
docker run -it someImage /bin/bash
```
のように使います。
（ "/bin/bash" の部分は、コンテナ起動時に実行するメインコマンドを指定しています。）

" -it " と書いているのは、" -i -t "と書いても良いです。
ただ、基本一緒に使うので短縮して書くのがスタンダードのようです。
それぞれ
　　[ -i ]オプション : interactive ( 対話型 )
　　[ -t ]オプション : tty ( 端末デバイス )
の意味です。

####[ -i ]オプション
シェルは何かしらの入力を受け取って処理をするコマンドプロセッサ？（何て言うの？）で、
対話型で入力を与えたい時は、標準入力からコマンドを与えて処理をしてもらいます。
（キーボード ≒ 標準入力 なので、キーボードでコマンドを打てばそれがシェルに届く）
なので、
コンテナの中で実行しているシェルに対話型で処理をしてもらうためには
コンテナの中で実行しているシェルと標準入力が繋がらないといけないです。
標準入力と繋がっていなければ、
コマンドを打っても、その入力はコンテナの中のシェルに届かず、
**コンテナの中のシェルにコマンドを実行してもらうことができない状態**になります。

そうならないようにするためのオプションが **[ -i ] オプション**で、
**「docker run で指定したコマンドの" /bin/bash "を対話型で使いたいから標準入力と繋いでね」**
という意味のオプションなんだと思います。


実際に、

```
1: docker run -it someImage
2: docker run -t someImage
```
1と2で挙動を比較してみたらイメージしやすかったです。
2で起動した場合は、" ls " や " exit " などを入力しても何も起こりません。
入力したコマンドがコンテナ内のシェルに届いていないのがわかります。

####[ -t ]オプション
こちらは自分の中でも完全にしっくりきている訳ではないのですが、
おそらくこういうことなんじゃないかという推測です。。。

" docker run " のコマンドを実行しているターミナルがあります。
で、
[ -t ]オプションを付けてコンテナを起動すると、
**そのターミナルの中に、コンテナ用の疑似的なターミナルを用意する**
ということだと思います。

これも実際に、

```
1: docker run -it someImage
2: docker run -i someImage
```
1と2を比較すれば、どういう状態かはすぐに体験できます。
2の場合、" ls " や " exit " などのコマンドを打てば、
それがコンテナ内のシェルに届いて、コマンドは実行されるのですが、
いつものようにターミナルを開いた時のような状態にはなっておらず、
ユーザー名やカレントディレクトリも出ていないし、タブによる入力補完なども機能しません。

イメージ的には、
キーボードの入力がターミナルを介することなく、生のまま反映される感じ。。
ただ、これによって何か大きな問題があるのかと言われれば特にはわからず、
シェルと対話できるし、ただ単にターミナルの機能？が使えない分、不便なのかなという感じです。

なので、[ -t ]オプションは
**「普段のようにターミナルを使えないと不便だからコンテナ用に疑似ターミナル用意するね」**
という意味のオプションなんだと思います。

##[ -d ]オプション

```
docker run -d someImage
```
のように、runコマンドを実行する時に
[ -d ] オプションを使うことがあるのですが、
これは**そのコンテナにアタッチせずにコンテナを起動する**という意味です。
（アタッチしない = デタッチの"d"）
つまりは、**バックグラウンドでコンテナを起動する**ということです。

このオプションで気になった点は、
バックグラウンドで実行してるのにコンテナがすぐに停止してしまうことでした。
なんとなく自分のイメージだと
**バックグラウンドで実行したら裏で動き続けてくれる**のかなと思ってたのですが、
単純にそういう訳でもなさそうでした。

例えば

```
docker run -d someImage /bin/bash
```
これでコンテナを起動すると、
起動したコンテナは即座に停止します。

これは指定した " /bin/bash "(メインコマンド) が起動直後に終了してしまうからで、
**コンテナは、バックグラウンドで実行しようがしなかろうが、**
**メインコマンドの実行が終わると自動で停止する**
という動作になっているからだと思います。

なので、
バックグラウンドで実行させ続けたい時は
勝手に終了することのないコマンドを、コンテナに与える必要があるようです。

先ほどの起動方法を

```
docker run -d -it someImage /bin/bash    // ※この話に関しては[ -t ]オプションはあってもなくてもいい
```

とすると、
" bin/bash " を対話型で実行するようになり、
メインコマンドが勝手に終了することがなくなり、
コンテナもバックグラウンドで動き続けるようになります。

[ -d ]オプションで大事な点は、
**「あくまでバックグラウンドで実行するだけでコンテナの挙動に差はないよ」**
ということだと思いました。

#おわりに

完全にDockerの動きを理解できた訳ではありませんが、
よく使うオプションで
「とりあえずこのオプション付けておいたら良いんでしょ」
という状態からは少し抜け出せたかなと思います。

同じようにDocker学び始めた方の理解の参考に
少しでもなれたら幸いです(^^)