Docker基礎 Dockerについて詳細に理解する

Docker初心者がDockerについて勉強した時のメモです。

## $ docker runは何をしているのか
### 結論: run = create + start
1つずつ見ていきます。

### runの挙動
```
$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
```
runを実行するとhello-worldのデフォルトコマンドであるテキスト出力のプログラムが実行されます。

### create 

```
$ docker create hello-world
4ef9a26766a189e365085710cb0c2fd71aecd60816f46d111287ccae8136c07b

$ docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                   PORTS     NAMES
4ef9a26766a1   hello-world   "/hello"   7 seconds ago   Created                            brave_panini
```
createだけを実行するとコンテナが作成されることがSTATUSから分かります。

### start
```docker
$ docker start 4ef9a26766a1
4ef9a26766a1

$ docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                      PORTS     NAMES
4ef9a26766a1   hello-world   "/hello"   6 minutes ago   Exited (0) 13 seconds ago             brave_panini
```
startだけを実行すると何も起きないがコンテナはexitになっているのが分かる。
startコマンドだけだと実際にデフォルトコマンドは実行されているが出力結果はターミナル上から見れない。
`-a`オプションをつけることで実行されるデフォルトコマンドの出力結果が見れる。

```docker
$ docker start -a 4ef9a26766a1

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
```

まとめると、`create`はコンテナの作成、`start`はデフォルトコマンドの実行をしていて、runはその両方を実行している。

## コマンドの上書き
```
$ docker run -it ubuntu bash
```
というコマンドの最後の`bash`の部分はデフォルトコマンド。
つまり`start`したときに実行されるプログラムのことでこのコマンド部分は変更できる。

```docker:例
$ docker run -it ubuntu ls
bin   dev  home  lib32	libx32	mnt  proc  run	 srv  tmp  var
boot  etc  lib	 lib64	media	opt  root  sbin  sys  usr
```
この場合は`ls`を指定しているので`run`すると`ls`が実行されている。
ちなみにこのコマンド部分を指定しないとどうなるかというと、

```
$ docker run -it ubuntu
root@a4e426ab6c07:/#
```
指定した時と同様に`bash`が起動している。元々コンテナ起動時に実行するコマンドは設定されているから。

`$ docker ps -a`でデフォルトで設定されているコマンドを確認できる。

```docker
$ docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED              STATUS                      PORTS     NAMES
a4e426ab6c07   ubuntu        "bash"     About a minute ago   Exited (0) 6 seconds ago              nifty_meninsky
8c15dc625d7d   hello-world   "/hello"   34 minutes ago       Exited (0) 34 minutes ago             quirky_merkle
```
ubuntuの場合は`"bash"`、hello-worldの場合は`"/hello"`というコマンドがデフォルトで設定されているのが分かる。

## -itは何をしているのか？
```
$ docker run -it ubuntu bash
```
のときおまじないとして`-it`を入力していたが`-it`は何をしているのか？
`-it`は`-i`と`-t`オプションを繋げた形で、
**`-i`はインプットを可能にする**、**`-t`は表示をきれいにする**ためのものです。
### -iがないと？
```
$ docker run -t ubuntu bash
root@a4e426ab6c07:/# ls

```
コンテナには入れるがコンテナ内で入力したことを受け付けてくれなる。
### -tがないと？

```docker
$ docker run -i ubuntu bash
ls
ls
bin
boot
dev
etc
home
```
`-t`は出力をきれいにしてくれるものなので、`-t`なしだと表示がきれいじゃない。
タブでの補完も効かなくなる。

## コンテナの削除
exit状態のコンテナは基本使うことがないので定期的に削除する。

- コンテナを単体で削除するコマンド

```docker
$ docker rm <container>
```
- Up状態のコンテナは削除できないのでUp状態のコンテナをexitにするコマンド

```docker
$ docker stop <container>
```
- exit状態のコンテナを全て削除するコマンド(便利)

```docker
$ docker system prune

WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N] 
```
注意にある`dangling images`というのはDockerfileからつくられたばかりのimageのこと。
dangling imagesには名前がついておらず`<none>`という表記になっている。

## コンテナとファイルシステムの独立性
同じdocker imageからコンテナを作っても作ったコンテナはそれぞれ独立している。
コンテナ間で干渉することもない。

```
$ docker run -it ubuntu bash
root@8143d007d614:/# touch test1
root@8143d007d614:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  test1  tmp  usr  var
```
```
$ docker run -it ubuntu bash
root@068c95f2344f:/# touch test2
root@068c95f2344f:/# ls
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  test2  tmp  usr  var
```

## コンテナに名前をつけてrunする
**コンテナに名前をつけるのはどんな時か？**

- 起動させ続けるコンテナを立てる時
- 共有サーバーを立てる時
- 他のプログラムで使用する時

```
$ docker run --name <name> <image>
```
でコンテナに名前をつけることができる。

```docker:例
$ docker run --name sample_container ubuntu

$ docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED             STATUS                         PORTS     NAMES
9c359b2e2182   ubuntu        "bash"     7 seconds ago       Exited (0) 6 seconds ago                 sample_container
```
既にあるコンテナと同じ名前にはできない。

## detachedモードとforegroundモード

### detachedモード
コンテナ起動後バックグラウンドで動いている

```docker
$ docker run -d <image>
```
### foregroundモード
コンテナexit後に削除 (一回きりのコンテナ)

```docker
$ docker run --rm <image>
```

# 参考
https://www.udemy.com/course/aidocker/