初心者でもわかるDockerってこんな感じ

# Dockerでの環境構築

## 概要
Dockerを使用して環境を構築する方法と、Docker事態の概要をまとめる

### Dockerとは
軽量で高速なコンテナ型の仮想環境が構築できるもの
＝仮装環境技術の一つ

- Dockerの特徴
1. ゲストOSが存在しない
仮想マシン→ホストOSの上にゲストOSを乗せる形で開発などを行う
Docker　　→ホストOSの上にDockerコンテナを乗せる形で開発する
　　　　　＝ゲストOSを使わなくて良いので仮想マシンより軽量になる

1. テスト環境と本番環境を同一にできる
→コンテナ内で作業するため、コンテナをそのまま本番環境で使用できる
　＝本番環境に移行した時に起こる予期せぬエラーなどを防止できる
1. 開発環境を共有できる
→コンテナの作成するファイルを共有することでチームで同一の環境で開発できる

----
※解説(ITエンジニア未経験野方向け)
→プログラミングを使って開発する際に様々な問題が起きるが、製作物ではない問題が起きることがある

例えば、
- OSによる問題
メンバーごとにPCが異なるため、同じソースコードを書いても別の挙動が起こる
- ソフトのバージョンによる問題
人によってインストールしてるソフトのバージョンが異なるため別の挙動が起こる

これらの問題は、開発する別で各々のPC環境の違いによる問題である。
解決策として、PCを揃えてバージョンを確認し合って揃えれば可能であるが毎回やるのは面倒。
上記は社内だと対応できるが、顧客に対して対応することは非現実的である。

そこで活躍するのがDockerで、同じ環境でソースコードを動かせるように統一できる優れものである。

----
## Dockerの中身について
### 覚える必要がある概念
- Dockerfile
- dockerhub
- Dockerイメージ
- Dockerコンテナ

### Dockerの流れ
まずはイメージをざっくり説明する。
Dockerではコンテナというものを作成して、それを起動してその場所で作業することで
同じ環境で開発ができるものである。

例え話として車で例えてみようと思う。

#### 前提：自分が車を注文するとして話を進める
それぞれ以下のように例える
- dockerhub　→車のカタログ
- Dockerfile→オプション
- Dockerイメージ→見積書
- Dockerコンテナ→車

＜車を注文する流れ＞
1. どの車にするか（dockerhub)
車を注文するにあたってディーラーのラインナップからまずは商品を選択する
1. 追加でカスタマイズしたい機能を追加（Dockerfile）
選択した車種から追加したいオプションがあれば追加する
1. 車の見積書を作ってもらう（Dockerイメージ）
注文したい車の詳細が決まったら見積書を作成する
1. 車を作ってもらって完成（Dockerコンテナ）
車が出来合ったら、車を使う

上記のような流れで一般的には新車を購入すると思う
これをDockerに当てはめると以下のようになる
1. dockerhub（カタログ）
開発で使用するプログラミング言語などがリストになっているので選択する
1. Dockerfile（オプション選択）
カタログの商品のままだと全てDockerが決めたデフォルト設定になる
追加したいオプションがあればDockerfileであらかじめ選択する
1. Dockerイメージ（見積書）
Dockerfileからイメージを作ってもらって、よかったらコンテナ化する
プログラミングのイメージで言うと「クラス」のようなイメージに近い
1. Dockerコンテナ（車）
実際にコンテナとして作成してコンテナ環境の中で開発する
プログラミングのイメージで言うと「インスタンス」のイメージに近い

※カスタマイズの必要がなく全てデフォルト設定で良い場合
→2.Dockerfileに関しては省略可能

### Dockerコマンド
#### Dockerイメージの作成は２種類の方法がある
1. dockerhubから直接持ってきてデフォルト設定のままイメージ作成
1. dockerfileでオプションを指定してイメージ作成
※事前に実行するカレントディレクトリにdockerfileを用意しておく
```bash:Dockerイメージ作成
#1.dockerhubから直接イメージを作成
>docker pull ruby：latest

#1-2.Dockerfileでオプションを選択して作成
>docker image build -t <イメージ名>:<タグ名> .
```
※ イメージ名とタグ名は任意で選択可能
　Dockerfileは違うディレクトリでもイメージ作成はできるが
　Dockerfileの場所を指定するコードが必要
 ##### 上記の使い分け
 ただ環境を使いたい、簡潔に環境を使いたい→１のやり方
 開発しやすいようにカスタマイズしたい→２のやり方（こっちが一般的）

----

#### Dockerコンテナの作成・起動も２種類の方法あり
1. コンテナを作成と起動を別々に行う方法
1. コンテナ作成と起動を同時に行う方法

```bash:Dockerコンテナ作成/起動
#1.Dockerコンテナの作成/起動を別々で実行
>docker container create [オプション]　<イメージ名>:<タグ名>
>docker container start　<コンテナ名orコンテナID>

#2.Dockerコンテナの作成/起動を同時に実行
>docker container run [オプション] <イメージ名>:<タグ名>

#docker runのオプションについて
--name <コンテナ名>　
    作成したコンテナに名前をつけられる
    コンテナを指定するときに使用できるのでつけた方が良い
-it
    インテラクティブモードを有効にする（対話モード）
    コンテナはシェルのように処理を送ったら対話形式で実行するものではない
    イメージとしてはコマンドを打ってもその処理を返したらすぐ終了するようになっている
    -itオプションをつけることで継続的にdocker環境を使用できる
    よくわからなければ、おまじないのような感じでつけておけばOK
-d
    バッググラウンドで起動できる
    起動後ターミナルが動き続けるのもあるため、その場合バックグラウンドで処理が望ましい
-v [ローカルのパス]:[コンテナ内のパス]
    ローカルファイルとコンテナファイルをマウントできる
    デフォルトではローカルのファイルとコンテナ内のファイルは依存関係はない
    しかし、マウントすることでローカルファイルと同期し変更を反映してくれるようになる
```
##### 上記の使い分け
前提→基本的にはrunを使う（楽だから）＝createはほとんど使っていない
後述するが起動もあればコンテナ停止もある
→コンテナ停止後、再度起動したい際はstartを使用しても良い

#### 曲者docker runについて
上記ではdocker run はコンテナ作成/起動と説明したが厳密にはそうではない場合がある。
それぞれ各条件を満たす場合で以下のようにrunの機能は変わる

1. 選択したイメージがない場合
→dockerhubから探して自動でイメージの作成も行う
＝イメージ作成＋コンテナ作成＋コンテナ起動

1. 選択したイメージがある＋コンテナが作成されていない場合
→選択したイメージからコンテナを作成して、起動する（新しいイメージは作成しない）
＝コンテナ作成＋起動
1. 選択したコンテナがすでに存在する場合
→選択したコンテナを起動する（新しいコンテナは作成しない）
＝コンテナ起動

-----
#### その他よく使用するコマンド

```bash:Dockerコマンドその他
#コマンドの実行（docker起動中に使用可能）
>docker exec <コンテナ名> <コマンド>
#上記のコマンドは重要なので具体例
※dockerコンテナ環境内のbashを起動させて処理したい場合
>docker containre <コンテナ名>　/bin/bash

#イメージの一覧表示
>docker image ls

#コンテナの一覧表示
#(起動中のコンテナのみ表示）
    >docker container ls
#（全てのコンテナ表示）
    >docker container ls -a

#コンテナの停止
>docker container stop <コンテナ名orコンテナID>

#イメージの削除
>docker image rm <イメージ名orイメージID>

#コンテナの削除
>docker container rm <コンテナ名orコンテナID>
```
-----
## まとめ
今回はdockerの使い方をざっくりとまとめてみました
イメージとコンテナが概念的な話なのでわかりにくいがコンテナにとりあえずしないと使えないことを
理解してもらえたらと思っています。
docker環境を使えば、ローカルにダウンロードするソフトの数も減るのでスマートになると思います。
今回は基本的な部分となり、もっと深いところは紹介できていません。
dockerで本格的に開発するのであれば
・具体的なdockerfileの書き方
・複数のコンテナを同時に管理できるdocker-compose
の学習も必ず必要だと思いますので、別途学習することをお勧めします。