Dockerを調べてみた

# はじめに
Docker本を読んだのでそのまとめです。

[プログラマのためのDocker教科書 第2版 インフラの基礎知識&コードによる環境構築の自動化](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEDocker%E6%95%99%E7%A7%91%E6%9B%B8-%E7%AC%AC2%E7%89%88-%E3%82%A4%E3%83%B3%E3%83%95%E3%83%A9%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98-%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AB%E3%82%88%E3%82%8B%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E3%81%AE%E8%87%AA%E5%8B%95%E5%8C%96-WINGS%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88/dp/4798153222/ref=sr_1_3?ie=UTF8&qid=1541999896&sr=8-3&keywords=docker)
[Docker実践入門――Linuxコンテナ技術の基礎から応用まで](https://www.amazon.co.jp/Docker%E5%AE%9F%E8%B7%B5%E5%85%A5%E9%96%80%E2%80%95%E2%80%95Linux%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E6%8A%80%E8%A1%93%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E5%BF%9C%E7%94%A8%E3%81%BE%E3%81%A7-Software-Design-plus-%E4%B8%AD%E4%BA%95/dp/4774176540/ref=sr_1_12?ie=UTF8&qid=1541999896&sr=8-12&keywords=docker)

https://knowledge.sakura.ad.jp/13265/

https://qiita.com/naga3/items/d1a6e8bbd0799159042e

https://qiita.com/gounx2/items/23b0dc8b8b95cc629f32

https://kiririmode.hatenablog.jp/entry/20180608/1528447002

# Dockerとは
* コンテナ型の仮想環境を作成、配布、実行するためのプラットフォームです
* アプリケーションの実行に必要な環境を1つのイメージにまとめる
* Dockerは、Linuxのコンテナ技術を使っている
* アプリケーションの実行環境をまとめることで可搬性を高め、スケーラブルな環境でも動作することを目指している

## コンテナとは
* コンテナはホストマシンのカーネルを利用し、プロセスやユーザなどを隔離することで、あたかも別のマシンが動いているかのように動かすことができます
* 軽量で高速(CPUやディスクやメモリ)

# Dockerでできるようになること
- ローカルのアプリケーション実行環境の起動を高速にできる。さらに実行環境を修正するときのカスタマイズ、再配布も容易
- 開発者が同じ環境で開発できる。更に、テスト環境と本番環境のアプリケーション実行環境を同じにできる
- Dockerの仕組みを利用するとインストール済みのアプリケーション実行環境を「イメージ」として固めてホスティングできる。Dockerが利用できる環境であればその「イメージ」をダウンロードしてすぐに各開発者が同じ環境でアプリケーションを実行できるようになる


参考
http://www.atmarkit.co.jp/ait/articles/1701/30/news037.html

# Dockerが解決すること
## 開発環境構築
* 既存の開発環境構築
  - 現在でもVagrant + Chefで環境構築している現場が多いのでしょうか？？私も以前Vagrant + Chefで環境構築する現場にいましたがその時の微かな記憶をたどると`プロビジョニングに失敗する`、`プロビジョニングに時間がかかる`、`仮想マシンが起動できない`、`起動が遅い`、`セットアップに時間がかかる`という問題が発生してたいように思います。おそらく各開発者のローカルのアプリケーションの実行環境やOS環境に差異があることが原因だったと思います。

→ 時間がかかるし、動かないときもある

*  Dockerを使った開発環境構築
  - アプリケーションの実行環境もまるごとコンテナで管理するので開発者は指定のイメージをダウンロードしてコンテナを起動するだけでアプリケーションを起動できる。
  - 複数の開発者が正確に同じ環境でアプリケーションの開発を進めることが可能
  - 本番、テスト環境、開発環境を同一にできる

→ 早い(軽くて便利)＆開発環境を同一(可搬性あり)にできる

参考
https://www.wantedly.com/companies/kurashicom/post_articles/102572


### Immutable Infrastructure
* 一度構築したインフラは変更加えることなく、破棄する、そして、新しいものを構築するという運用方法
  - 以前は本番環境と同じ状態のテスト環境を用意してテスト実施。本番にもその設定を反映。しかしそもそもテスト環境が本番と同じという確認が難しく、差異が含まれていて本番だと動かないという状況があった
  - Dockerを使えば再作成した環境をそのままテストして、問題がないことを確認してそのままその環境を本番で使う。差異がないので本番だと動かないという状況が少ない


### Infrastructure as Code
* コードでインフラ構成を管理することで可視化、属人化を排除する運用方法
  - 以前はインフラの設計書やパラメータシートと本番環境で差異があり、うまく動作しないことがあった
  - Dockerfileを利用することでインフラの構成情報を可視化して、属人化を排除。本番環境のインフラ構成と同じ構成をDockerfileで確認きるようになる

### 継続的インテグレーション
* アプリケーションを追加/修正する毎にテストすることで確実に動作するコードを保持する手法
  - しかし、異なる環境でも同じように動く保証はない。環境の差によってテスト環境では動く、本番では動かないということが起こるかも

  - Docker → テスト済みのアプリケーション実行環境をそのまま本番環境にデプロイ可能。テスト環境で動作すればその環境を本番環境に移動させるだけなので本番環境でも動くはず。テスト環境と本番環境で同一な環境を利用できることで継続的インテグレーション達成できる
 
### 継続的デリバリー
* 常にアプリケーションが本番環境にリリース可能な状態を継続的に保っていること
  - しかし、アプリケーションのバージョンアップ作業は、いろいろ大変。テスト環境と本番環境の差異によってデプロイが失敗したり、アプリケーションが動かなかったり。このままじゃ継続的デリバリーを達成できない。
  - Docker → テスト済みのアプリケーション実行環境をそのまま本番環境にデプロイ可能。テスト環境で動作すればその環境を本番環境に移動させるだけなので本番環境でも動くはず。テスト環境と本番環境で同一な環境を利用できることで継続的デリバリー達成できる

参考
https://www.slideshare.net/zaruhiroyukisakuraba/railsdocker-78973487


# dockerコマンド
## docker container コマンド
* コンテナを管理する docker container サブコマンド群や、イメージを管理する docker image サブコマンド群の下で、これまでのコマンドが使えるようになります
* 例えばdocker container runとdocker runコマンドは同じ。だがコマンドが増えたのでdocker container サブコマンドに変更になった
* コンテナを管理コマンド
  - `docker container サブコマンド群`
* イメージを管理
  - `docker image サブコマンド群`

## Dockerイメージダウンロード
* docker pull nginx(イメージ名:タグ)
* イメージ名
  - ユーザー名/イメージ名になる。公式のイメージはイメージ名のみ
* イメージのタグ
  - イメージ名:タグ タグない場合最新取得

## コンテナの確認
docker container ps



## コンテナ作成
docker container create

## コンテナ生成・起動
* docker container run
* コンテナ上で任意のプロセスを起動
* docker container run プション イメージ名 引数
* オプション
  - t コンテナの標準出力をホストの標準出力につなげる
  - i ホストの入力をコンテナの標準出力につなげる
  - --name コンテナ名。省略するとランダムなコンテナ名が割り当てられる
  - ttyとは、標準入出力となっている端末デバイスを表示するコマンド

## コンテナの停止、開始
docker container sotp|start コンテナ名前

https://qiita.com/zembutsu/items/6e1ad18f0d548ce6c266


## コンテナの対話的実行
```
sudo docker container run -it --name "test1" centos /bin/cal
      July 2019     
Su Mo Tu We Th Fr Sa
    1  2  3  4  5  6
 7  8  9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
```
## コンテナのバックグラウンド実行

```sh

$ sudo docker container run -d centos /bin/ping localhost
09fe86b9e25edc292f462099ed8122211a717e0292240160f12f82eb097446a7
$ sudo docker container ps
CONTAINER ID        IMAGE               COMMAND                 CREATED             STATUS              PORTS               NAMES
09fe86b9e25e        centos              "/bin/ping localhost"   3 seconds ago       Up 2 seconds                            infallible_goldberg
```


## dockerイメージの作成
docker  build -t sample:1.0 ./Dockerfileの場所


## コンテナへの接続
```
docker exec -ti コンテナ名 bash
```
dockerコンテナでシェルを実行してコンテナの入出力をつなげる


# Dockerfileの書き方
## コマンドの実行(RUN)
- ベースイメージに対して、アプリをインストール、設定するなど
- シェル形式
  * RUN echo "aaaa"
- Excec形式(シェルを介さず実行)
  * Run["echo","aaaa"]

## デーモンの実行(CMD)
- シェル形式
  * CMD nginx -g 'daemon off'
- Excec形式(シェルを介さず実行)
  * CMD["nginx","-g","daemon off"]

## デーモン実行(ENTRYPOINTとCMDの組み合わせ)
* 引数を指定してデーモンを実行する場合

```
//実行したいコマンド指定
ENTRYPOINT ["top"] 

// topの引数を指定(デフォルト)
// container run 時に引数を指定するとそちらが優先される
CMD ["-d"," 10"]   
```

## ボリュームのマウント
* VOLUME["/マウントポイント"]
* 永続化が必要なデータはコンテナ外のストレージに保存する
* ボリュームとはは Docker が管理するデータ領域を Container 上にマウントする機能

```sh
$ sudo docker volume ls
DRIVER              VOLUME NAME
```
最初はなにもない



# 複数コンテナの配置
## DockerCompose
* `同一ホスト上`の複数のコンテナをまとめて管理するためのツール
* docker-compose.yml

## docker-compose.yml
### コンテナの環境変数の設定
* Environment:
  - 変数名=hoge
  - ./環境変数が書かれたファイル名

### ボリュームの指定

```sh

volumes:
　//dockerのデータ領域にあるボリュームにマウントされる
  - /var/lib/mysql
  //ホスト側のパスを指定してマウントもできる
  // ホストディレクトリパス：コンテナのディレクトリパス
  - cache/:/tmp/cache
```
 

### 依存

```
depends_on:
      - mysql
```

mysqlコンテナを先に立ち上げ、またphpコンテナ側からmysqlコンテナにアクセスできるようになります。


## docker-composeコマンド
* 複数Dockerコンテナの起動
  - docker-compose up
* コンテナの確認
  - docker-compose ps
* バックグラウンドで実行
  - docker-compose -d (コンテナの標準入出力がシェルにならない)

# まとめ
詳しくは書籍を参照してください。わかりやすかったです