(No.7) おじさんが、LINE風アプリを開発する - 仮想機械、コンテナについて調べてみるよ - その２

# 前回までのあらすじ
- GitHubを利用して、おじさんの成果物を公開する準備が整いつつあるよ
    - [(No.1) おじさんが、Git・GitHubを利用できるようにしてみる - GitHubにユーザを登録する](https://qiita.com/resojisan/items/4cd09b7a5f33ca8a925d)
    - [(No.2) おじさんが、Git・GitHubを利用できるようにしてみる - GitHubを利用してみる](https://qiita.com/resojisan/items/75dcc83ea55af0db329f)
    - [(No.3) おじさんが、Git・GitHubを利用できるようにしてみる - GitHubからリポジトリを複製（クローン）する](https://qiita.com/resojisan/items/f119d8b71e3bba9eadec)
- 目標を立てたよ、LINE風アプリが作れるようになることを目指すよ
    - [(No.4) おじさんが、何を開発するのか目標を立てるよ](https://qiita.com/resojisan/items/6a8690d21fe9ab00189d)
    - [(No.5) おじさんが、LINE風アプリを開発する - メッセージの送受信を考えてみるよ](https://qiita.com/resojisan/items/6418171fcc80bc3122cf)
- 開発環境の差異を軽減することが出来ないか考えてみるよ
    - [(No.6) おじさんが、LINE風アプリを開発する - 仮想機械、コンテナについて調べてみるよ - その1](https://qiita.com/resojisan/items/b08490e013067994d11e)

# 調査の目的
- おじさんの開発環境はmacOS。おじさん以外の人でも試すことの出来る成果物を（なるべく）作成したいんだよ。
    - OS（オペレーティングシステム）等の環境差異(macOS? Windows? Linux?)が問題になりそうだよ。
    - 開発環境の差異を改善(解消？)する手段として、仮想機械やコンテナと呼ばれるものが利用出来るかもだよ？？
    - 目的に合致する技術があるのか調査してみるよ。
- [前回の調査](https://qiita.com/resojisan/items/b08490e013067994d11e)で、仮想マシンについて何となく理解したような気がするよ。
- 今回はコンテナについて調べてみるよ。

## 前提
- （事実上の標準と考えられる）[Docker](https://www.docker.com/)を対象に調査してみたよ。
- おじさんが取り扱うコンテナに関する情報は、Docker以外は考慮していないよ。  
（Docker以外の世界では通用しない解釈が含まれているかもしれないよ）
- Dockerも日々進化するみたいなので、今日時点では正しい理解でも、明日になったら誤りになる可能性があるよ。
    - 実際に、Qiita内外の記事をみても誤った内容を散見するよ。（執筆当時は正しかったのかもしれないね）
    - 何かを開発するときは、その都度、再調査するべきだとおじさんは確信したよ。
        - 「覚える」よりも「理解する」方が圧倒的に効率が良いって実感した次第だよ。（えっへん）
            - 覚える／理解するに関わらず、かつて有益だった「情報」が、時の経過と共にゴミになる事実は、おじさんにとっては喜ばしいことだと思ったよ。（新しい技術の前では、誰もが初心者になるってことだから・・・）

## おじさんが調査して感じたコンテナで重要そうなこと
### （１）仮想マシンを必要としないため、アプリを高速に起動＆実行することが出来る
- 仮想マシンを必要とせず、アプリを実行する環境を隔離（まるで独立したOSの上でアプリが動作しているかのように振る舞う）することが出来るみたいだよ。
- 他のアプリやコンテナから隔離されたアプリを実行する空間を、コンテナと呼ぶみたいだよ。
- コンテナは、ホストOS上で動作する１アプリのようなもの。 仮想マシンと異なりゲストOSの起動すらも不要みたい。
- 仮想マシンが不要のため、秒単位で起動&実行。仮想マシンを使用する場合と比較して高速らしいよ。
    - アプリの実行環境を「作っては捨てる」を、高速に繰り返すことが出来るみたい。
        - 必要なもの（コンテナ）を必要なときに必要なだけを実現することにも貢献するみたい。
        - サーバやアプリのバージョンアップ＆修正を素早く実施することが出来そう。
            - 試作→運用→改善→運用→改善→運用を繰り返すことにも貢献しそう。

### （２）アプリの実行環境は手順書(Dockerfile）から自動作成する
- アプリの実行環境は手作業で作成するのではなく、[手順書（Dockerfile）](https://docs.docker.com/engine/reference/builder/)を作成することで、アプリの実行に必要な[イメージファイル](https://docs.docker.com/get-started/)を自動的に作成することが出来る。
- イメージファイルは、アプリを実行するために必要なものが梱包されたもの。
- イメージファイルを元に、コンテナが作成され、コンテナ内のアプリが実行される。
    - 手順書（Dockerfile）は、ただのテキストファイルなので、Git等を使用した履歴管理（変更点の確認等）が簡単に出来そう。
- イメージファイルまたはDockerfile(と、イメージファイルの作成に必要な何か）を配布すれば、おじさんのコンピュータ以外の環境でもアプリを実行することが可能になるみたい。

### （３） コンテナの実行に必要なファイルを、賢く管理するエコな仕組みがある
- [About storage drivers](https://docs.docker.com/storage/storagedriver/)
    - 複数のコンテナが起動することを前提に考えると理解しやすくなると、おじさんは感じたよ。
        - 例えば、一つのイメージファイルから、100台のコンテナを起動するとき、１つのコンテナの起動に必要なファイルが10GBとする場合、10GB x 100台=1TB(1,000GB)ものファイルが必要になってしまう・・・。といった課題を想像することが出来るよ。
            - [Googleの場合、毎週20億のコンテナを起動している](https://cloud.google.com/containers/)らしいよ・・・。
    - コンテナ間の差分だけを保管することが出来れば、コンテナ間で重複するファイルが不要になるのでは？といったアイディアだと、おじさんは勝手に解釈したよ。
    - 読み取り専用のファイルは、コンテナ間で単純に共有することが出来るけど、書き込みが伴うファイルの場合は、コンテナごとにファイルの内容に差が出来るため、他のコンテナとファイルを共有することが出来なくなる。
        - 書き込みが発生したタイミングではじめて、コンテナごとにファイルを複製する仕組みを採用したみたいだよ。これを[コピーオンライト(CoW)](https://docs.docker.com/storage/storagedriver/)と呼ぶみたい。
            - 頻繁に書き込みが発生すると、コピーオンライトの処理が負担になるみたい。
            - [コンテナが削除されると、コンテナが書き込みしたファイルは消えてしまう](https://docs.docker.com/storage/)みたいだよ。（コンテナ内でつくられたファイルは、コンテナの寿命と共に消える）
                - 高頻度のファイル書き込みが想定される場合や、書き込みしたファイルが消えてしまっては困る場合の考慮として、コンテナの外にファイルを書き込む手段が用意されているみたいだよ。
                    - [ヴォリューム](https://docs.docker.com/storage/volumes/)
                        - Windows、Linuxのいずれのコンテナでも機能するみたいだよ。
                        - 複数のコンテナ間で安全にファイルを共有することが出来るみたいだよ。
                        - クラウドに保管したり、暗号化したり便利機能があるみたい。バックアップも簡単だって。
                        - コンテナを停止しても書き込みしたファイルは残るよ。
                        - [Dockerでファイルを保存する最良の方法と書かれているよ。](https://docs.docker.com/storage/)
                    - [バインドマウント](https://docs.docker.com/storage/bind-mounts/)
                        - ホストOSのファイルシステムを利用するみたい。ヴォリュームよりも機能面の制限はあるが、高性能とあるので、読み書きの性能を最大にしたい時に使うのかな・・・。
                        - ホストOSに直接ファイルを読み書きすることを意味するので、バインドマウントを使用するコンテナは、ホストOSのファイルシステムに依存することになるのだと思うよ。
                        - コンテナを停止しても書き込みしたファイルは残るよ。
                    - [tmpfsマウント](https://docs.docker.com/storage/tmpfs/)
                        - ホストOSのメモリに一時的にファイルが保存されるみたいだよ。
                        - コンテナが停止すると書き込みしたファイルは消えるよ。ただし、[ヴォリュームに書き込みするよりもパフォーマンスが良いみたい](https://docs.docker.com/storage/volumes/)なので、最終的には消えてしまっても構わないような、一時的なファイルの書き込み先として最適みたいだよ。
                        - コンテナ間で共有することが出来ないみたいだよ。

### （４）ホストOSをLinuxにする必要がある
- コンテナを実現するために、Linuxの機能を使用するため。
    - 仮想マシンと組み合わせることで、macOSやWindowsでも利用することが可能。
        - macOS、Windowsの場合は、ハイパーバイザーを使用して、仮想マシンを起動。仮想マシン上でLinuxとコンテナを実行する。
            - → [Docker Desktop](https://www.docker.com/products/docker-desktop)
            - ホストOSがWindowsで、なおかつ、Windows環境のコンテナを動作させる場合は、[仮想マシンを介さずに直接動作するみたいだよ。](https://docs.microsoft.com/ja-jp/dotnet/standard/microservices-architecture/container-docker-introduction/docker-defined)
            - [Windowsの場合、WSL2の登場によって、より高速にLinux環境のコンテナが動作するようになるのかも？](https://devblogs.microsoft.com/commandline/announcing-wsl-2/)
                - 「WSL 2 uses the latest and greatest in virtualization technology to run its Linux kernel inside of a lightweight utility virtual machine (VM).」
        - ハイパーバイザーを使用することの出来ない旧環境の場合は、VirtualBoxと呼ばれる仮想マシンを使用する。
            - → [Docker Toolbox](https://docs.docker.com/toolbox/)

### （５）Dockerの種類
- [Docker CE](https://docs.docker.com/install/)
    - 無償だよ。
- [Docker EE](https://docs.docker.com/ee/supported-platforms/)
    - CEとの機能面の差異は、おじさんにはまだよくわからないけど、商用利用時の便利な機能があるのかもしれないね。
        - Dockerを稼働させる環境（や、OSの組み合わせ等）のお墨付き（認定：動作確認済み＆サポート）が得られるようだよ。
            - おじさんの場合は、趣味なので、自己責任で良いけど、おじさん個人のノリや運任せが許されない状況の場合は、公式に動作保証してくれるのは、とても嬉しいことかもしれないね。
        - CEとは異なり、各リリース（バージョン？）に24ヶ月のサポートがあるみたいだよ。最低でも2年間は安心して運用出来るってことかな。
        - 価格は非公開のようで、おじさんにはわからなかったよ。
            - 代理店：[Docker 価格表](https://www.xlsoft.com/jp/products/docker/price.html)
            - ナゾの記事にナゾの価格が：[Why your company should consider shelling out for the new Docker Enterprise Edition](https://www.techrepublic.com/article/why-your-company-should-consider-shelling-out-for-the-new-docker-enterprise-edition/)

## 調査の目的に対する結論（仮想マシン？コンテナ？両方？）
- 調査の目的
    - 開発環境の差異をなるべく軽減したい
- 結論
    - 開発環境では、仮想マシン + Dockerを利用して、開発環境毎に異なるOS（Windows/macOS/Linux等）の差異を改善する。
    - 本番環境では、ホストOSにLinuxを採用し、Linux上でDockerを動作させる。
        - 仮想マシンもコンテナも両方使用する。


# あとがき
- 次回は、Dockerを導入してサーバを立てて、少しでも早くアプリの完成に近付きたいと思うよ！！
- [「クラウド・ネイティブ開発運用ソリューションのご紹介」の資料](https://public.dhe.ibm.com/software/dw/jp/cloud/microservices-docker-k8s-briefing.pdf)は、概要をぼんやり理解する助けになったよ。おじさんの場合はだけど・・・。
- おじさんの自習ノートを恥ずかしいけど晒しておくよ。（恥）


## おじさんの自習ノート
### 自習ノート１：仮想マシンの復習
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419842/a69cdb7b-22b2-0715-1eca-ace4ba717a7a.png)

- ホストOSタイプ、ハイパーバイザータイプの仮想マシンでは、コンピュータのハードウェア〜OS（ゲストOS）までを、仮想化するものだったよ。


### 自習ノート２：コンテナ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419842/853378c0-a143-5d81-ee83-e56fac02bd36.png)

- コンテナでは、ホストOSより上を仮想化（隔離）するよ。これは仮想マシンと比較して大きく異なることだよ。
- 上図のコンテナA〜Cは、それぞれ独立したOSの上で動作しているかのように振る舞うよ。
    - 仮想マシンを利用せずに、アプリを実行する環境を隔離（まるで独立したOSの上でアプリが動作しているかのように振る舞う）することが最大の特徴だよ。
- Dockerは、コンテナを作成したり、複数のコンテナを管理する機能を提供するものだよ。
- DockerのホストOSには、Linuxと呼ばれるOSを使用する必要があるみたいだよ。（[例外あり](https://docs.microsoft.com/ja-jp/dotnet/standard/microservices-architecture/container-docker-introduction/docker-defined)）

### 自習ノート３：仮想マシンが無いのに・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419842/5ef0b247-ebe1-f331-8b34-2a487e4b668d.png)

- Linuxには様々な種類が存在するみたいだけど、上図のようにLinux B、Linux Cみたいに、ホストOS(Linux A)とは異なる種類のLinuxを動作させるようなことが出来るみたいなんだよ・・・。
- 仮想マシンがないのに不思議なことだよ・・・。
    - Linuxと呼ばれるOSの機能を利用して実現することなので、Linuxを少しだけ知っておく必要があるみたいだよ。

### 自習ノート４： Linux
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419842/effd55a5-659f-10ba-3223-b0f33715388e.png)

- 用語が多くて、理解するのが難しかったよ。
- おじさんの現時点のLinuxに対する理解力は次のようなものだよ。（おじさんの勉強が進むにつれて、見解が変化するかもだよ）
    - LinuxはOS（オペレーティングシステム）の一種。
    - [カーネル](https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB)、[Linuxカーネル](https://ja.wikipedia.org/wiki/Linux%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB)
        - Linuxカーネルとは、OS（オペレーティングシステム）の主たる機能を指すもので、ハードウェア（CPUやメモリ、ストレージ等）の操作／管理、アプリの実行／管理の仕事を担っているよ。
    - [システムコール](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%82%B3%E3%83%BC%E3%83%AB)を通じて、アプリはOSの機能にアクセスすることが出来るみたいだよ。
    - アプリをゼロから開発するのは困難なため、アプリの開発に必要なプログラムや機能を、複数のアプリで再利用出来るように切り出して部品にしたものを[ライブラリ](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA)と呼ぶみたいだよ。
    - ライブラリ（プログラムや機能を切り出した部品）を利用することで、アプリ開発の難度を下げたり、生産性を高めることが出来るみたいだよ。
    - Linuxカーネル、ライブラリ、アプリを組み合わせて、macOSや、Windowsのように簡単に利用出来るようにしたものを、[Linuxディストリビューション](https://ja.wikipedia.org/wiki/Linux%E3%83%87%E3%82%A3%E3%82%B9%E3%83%88%E3%83%AA%E3%83%93%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3)と呼ぶようだよ。
        - [Ubuntu](https://ja.wikipedia.org/wiki/Ubuntu)や、[CentOS](https://ja.wikipedia.org/wiki/CentOS)など、様々な種類のLinuxディストリビューションが存在するよ。
        - [Android](https://ja.wikipedia.org/wiki/Android)のOSにも、Linuxカーネルが含まれているみたいだよ。


### 自習ノート５： 再びコンテナ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419842/5ef0b247-ebe1-f331-8b34-2a487e4b668d.png)

- 上図のように、各コンテナは、ホストOSとは異なる種類のLinuxを使用することが出来るようにみえるけど・・・
    - 実際は、ホストOSのLinuxカーネル上でコンテナが動作するみたいなんだよ。
    - 上図では、Linux B、Linux Cと、コンテナごとに異なる種類のLinuxディストリビューションが動作しているけど、実際は、Linuxカーネル以外のOSを構成するプログラムやライブラリを、コンテナごとに変更出来るようにすることで実現するみたいだよ。
        - ホストOS側のLinuxカーネルのバージョンが、Linuxディストリビューションが想定するバージョンと異なっていたとしても、正常に動作することが可能なようだよ。（Linuxカーネルの後方互換性が高いため）
        - ホストOSのLinuxカーネルには存在しない機能を、Linuxディストリビューションが求める場合には問題が生じるかもしれないよ。
            - ホストOS側のLinuxカーネルと、各コンテナが使用するLinuxディストリビューションの種類やバージョンには注意が必要かもしれないってことだよ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419842/5ef808de-5346-0f72-36e5-4474a48dd2b5.png)


### 自習ノート６： コンテナ型の仮想化を実現する技術
- 仮想マシンを利用せず、コンテナと呼ばれる独立した空間を実現するために、Linuxの機能を使用するみたいだよ。
    - [cgroups](https://docs.docker.com/glossary/?term=cgroups)
        - プロセスへの物理資源（CPUやメモリ等）の割当や制限
    - [namespace](https://docs.docker.com/glossary/?term=namespace)
        - OS固有資源（プロセス、ネットワーク等）の隔離
    - [pivot_root](https://blog.docker.com/2015/06/runc/)
        - コンテナ内のファイルシステムを変更する
    - ファイルシステム、ボリューム・マネージャ
        - ストレージ・ドライバ（OverlayFS、AUFS、Btrfs、Device Mapper等）
- おじさん、頭が爆発しそうなので、深追いはしないよ・・・。
    - Dockerを利用せずに、Dockerと同等のことが出来るのかどうかを試すのも面白そうだね・・・。

### 自習ノート７： Docker Desktop for Mac and Windowsの不思議
- Docker等のコンテナ技術はLinuxカーネルの機能に依存しているにも関わらず、macOS版、Windows版のそれぞれがリリースされている。
- 非Linux環境下で、Dockerが動作するのだろうか？
    - Linuxカーネルに依存する仕組みのため、macOSもWindowsも、仮想マシン（の上でLinuxカーネルを稼働）経由で動作させることになるみたいだよ。
        - [macOSの場合](https://docs.docker.com/docker-for-mac/install/)は、ハイパーバイザー(Hypervisor Framework)を使用した仮想マシン上で動作。
            - macOS Sierra 10.12以降であれば良いみたいだよ。
        - [Windowsの場合](https://docs.docker.com/docker-for-windows/install/)は、[Windowsイメージであれば仮想マシンを介さずに直接動作するみたいだよ。(老舗の維持を感じたよ!!）](https://docs.microsoft.com/ja-jp/dotnet/standard/microservices-architecture/container-docker-introduction/docker-defined) Linuxイメージの場合はハイパーバイザー（Hyper-V）を使用した仮想マシン上で動作するみたいだよ。
            - [OSの種類等のシステム要件が明確に書かれている](https://docs.docker.com/docker-for-windows/install/)ので要注意だね。
            - 例：Windows 10 64bit: Pro, Enterprise or Education (Build 15063 or later).
        - ハイパーバイザーを使用することの出来ない旧環境の場合は、VirtualBoxと呼ばれる仮想マシンを使用する。
            - → [Docker Toolbox](https://docs.docker.com/toolbox/)


# 用語集
[Docker glossary](https://docs.docker.com/glossary/)

# 参照・メモ
[Docker frequently asked questions](https://docs.docker.com/engine/faq/)
[How is Docker different from a virtual machine? ](https://stackoverflow.com/questions/16047306/how-is-docker-different-from-a-virtual-machine)
[Docker について](https://docs.microsoft.com/ja-jp/dotnet/standard/microservices-architecture/container-docker-introduction/docker-defined)
[クラウド・ネイティブ・コンピューティング最新技術トレンドのご紹介](https://public.dhe.ibm.com/software/dw/jp/cloud/microservices-docker-k8s-briefing.pdf)
[アーキテクチャの理解](http://docs.docker.jp/engine/introduction/understanding-docker.html)
[コントロールグループについて (CGROUP)](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/6/html/resource_management_guide/ch01)
[DockerをRed Hatはどのように見ているのか](https://www.slideshare.net/Yuryu/docker-at-iij-201412)
[ストレージ・ドライバの選択](http://docs.docker.jp/engine/userguide/storagedriver/selectadriver.html)
[イメージ、コンテナ、ストレージ・ドライバの理解](http://docs.docker.jp/engine/userguide/storagedriver/imagesandcontainers.html)
[Device Mapper ストレージ・ドライバの使用](http://docs.docker.jp/engine/userguide/storagedriver/device-mapper-driver.html)
[device-mapper 解説](http://lc.linux.or.jp/lc2009/slide/T-02-slide.pdf)
[ABI(Application Binary Interface)](https://ja.wikipedia.org/wiki/Application_Binary_Interface)
[カーネル](https://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB)
[Linuxカーネル](https://ja.wikipedia.org/wiki/Linux%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB)
[「Dockerイメージ」のポータビリティとLinuxカーネルのABI (中井悦司)](https://www.school.ctc-g.co.jp/columns/nakai/nakai43.html)
[Dockerを支える技術](https://www.slideshare.net/enakai/docker-34668707)
[なぜDockerではホストOSと違うOSベースのコンテナイメージが動くのか](https://qiita.com/kirikunix/items/33414240b4cacee362da)
[Containers vs. VMs: What’s the difference?](https://www.ibm.com/blogs/cloud-computing/2018/10/31/containers-vs-vms-difference/)
[仮想化の概要](https://docs.oracle.com/cd/E37520_01/b69423/vmusg-virtualization.html#vmusg-hypervisor-table)
[Oracle VMの仮想化とは](https://www.oracle.com/technetwork/jp/articles/nakajima-ovm-095944-ja.html)
[ハイパーバイザーとシステム仮想化について学び、クラウド環境で機能する仕組みを理解する](https://www.ibm.com/developerworks/jp/cloud/library/cl-hypervisorcompare/index.html)
[1日5分のXen理解: 第1回 仮想マシンとは何か？](https://www.ibm.com/developerworks/jp/linux/library/itm-review1/index.html)
[これだけは知っておこう！いまどきのクラウド用語 2019](https://www.ibm.com/blogs/think/jp-ja/zd1-innovate-glossary/#container)
[コンテナとは何か](https://www.ibm.com/blogs/solutions/jp-ja/what-is-containers/)
[GOOGLE のコンテナ](https://cloud.google.com/containers/?hl=ja)
[マイクロサービスとコンテナーを併用すべき理由](https://www.ibm.com/developerworks/jp/library/why-should-we-use-microservices-and-containers/index.html)
[What is a Container?](https://www.docker.com/resources/what-container)
[Get Started, Part 1: Orientation and setup](https://docs.docker.com/get-started/)
[Docker overview](https://docs.docker.com/engine/docker-overview/)
[Docker道場「Dockerの基本概念」0825インフラ勉強会資料](https://www.slideshare.net/zembutsu/docker-basis)
[Docker ドキュメント日本語化プロジェクト](http://docs.docker.jp/)
[AWSでDockerを扱うためのベストプラクティス](https://www.slideshare.net/AmazonWebServicesJapan/awsdocker)