仮想化を知るには、仮想化ではないとは何かを知るべきだ【Dockerコンテナ・グレートジャーニー①】

# Dockerコンテナ・グレートジャーニー
皆さん、エンジニアとしては必須級の知識となっているDockerコンテナは使っていますでしょうか？
この記事ではDockerコンテナについて、仮想化とは何かという部分からDockerコンテナを実際に動かすまで、その全体像をイメージで掴めるように解説していきます。
Dockerコンテナを使ったことが無い方はもちろん、普段なんとなく使っている方も、この機会にDockerコンテナとは何なのかについて０から学ぶ、始まりの旅グレートジャーニーにご案内します。

本記事はグレートジャーニーの第１回、そもそも仮想化とは何か？　というお話です。

## 対象
* Dockerコンテナを触ったことが無い人
* Dockerコンテナは触ったことがあるけど、Webに書いてあるコマンドを打つだけで、中身をあまり理解していない人
* イメージを交えながらでないと理解が深めにくい（筆者のような）人

## 旅路（インデックス）
長くなるので記事を分割しています。
1. そもそも仮想化とは？　仮想化ではないシステムとは？　<font color=orange>【⇦本記事】</font>
1. [Dockerコマンド基礎（環境構築～ubuntu/httpdコンテナでのコマンド実行）](https://qiita.com/Toyo_m/items/94de894a8558d94b02d1)
1. [Dockerのストレージについて](https://qiita.com/Toyo_m/items/95a2543c07dc5b126208)
1. [Dockerのネットワークについて](https://qiita.com/Toyo_m/items/52fa81948d5746dd2afc)
1. [Docker-compose でコンテナをまとめる](https://qiita.com/Toyo_m/items/ef14658629d3118003ea)
1. [Docker image と Dockerfile](https://qiita.com/Toyo_m/items/5713f85a9d5ff8d9cc0d)
1. [AWS ECS で Dockerコンテナを走らせる](https://qiita.com/Toyo_m/items/90df3c90353ed6fb3fd8)

（※構成は変更になるかもしれません）

# 【主題】そもそも仮想化とは？　仮想化ではないシステムとは？
コンテナとは何でしょうか？
GoogleやChaGPTに聞いてみると、
* コンテナとは仮想化の一種
* 軽量で可搬性に優れる
* OSの違いを意識せず、アプリケーションを実装できる

ということだそうです。これで意味が分かる方はこの記事を読む必要が無いかもしれませんが、少なくともかつての私は全く意味が分かりませんでした。特に仮想化と言われても「なるほど？」としか言えない状態で、そのメリットもいまいちピンときませんでした。仮想化、コンテナ、Docker、それぞれ違う意味の単語なのですが、全部を頭に詰め込もうとして混乱していました。
最近ようやく理解が進んできたのですが、ここまで来てなぜこんなに理解が難しかったのか原因を考えてみました。たどり着いた原因として <font color="red">**仮想化ではない状態とは何かを理解せずに仮想化の話をする**</font> のでややこしくなるのだと思いました。
ですので今回の旅路では、最初に最も基礎的で重要な『仮想化』について、いえそのさらに前の『仮想化ではない』システムについて説明します。

## 仮想化ではないとは？
仮想化を学ぶために、まずは仮想化ではないシステムとは何かを知ることが大切だと言いました。ただ、これは少し難しいです。
ITに関わる人なら教養として知っておいて損はない内容です、聞きなれない方にとってはかなり難しいと思うのでイメージ図でなんとなく全体像を掴んでもらえたら幸いです。
`BIOS(バイオス)`とか`Bootloader`とかいう単語が登場しますが「なんかそういう機能があるんだな」程度に思っていただいて大丈夫です。

### OSはBIOSとBootloaderが展開している
突然ですが、あなたのWindows（もしくはMac）PCが、どうやってOSを起動させているかご存じですか？
あなたのPCの電源スイッチはWindowsOSのスイッチではありません。もう少し複雑な仕組みがあるのです。WindowsPCを起動するにあたっては、BIOSとBootloaderというものが活躍します。

Windowsが立ち上がるざっくりと書くと下図の感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618997/1e0613b2-bc2a-2103-c47b-fafecbff14e6.png)
(ブートローダー = Windows Boot Manager と考えていただいて大丈夫です)

* BIOS: デバイスを初期化して、各種ハードウェアのチェックや設定反映を実行。その後Bootloaderを起動する。PCのスイッチを入れたあと、一番最初に起動するソフトウェア。
* Bootloader: PCのストレージにあるWindowsOSを、PCのメモリに展開する。こいつがWindowsの準備をしてくれる。

この2つの機能が連携することによって、ストレージからメインメモリにWindowsOSを展開し、アプリケーションを起動することができるのです。下の図で「メモリ」の部分を左から順に追ってもらえると、どのようにWindowsが起動されるかがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618997/474ce92d-fa5c-6b8a-0027-73e990f9c81f.png)

というわけで、WindowsOSを起動させることができました。

 ↓ 最終的に、Windowsは下図のような構成になり、これが仮想化ではない状態です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618997/a0ee3420-1569-3e5d-ca6e-0c54bc32259b.png)

### 仮想化ではない環境で、Linuxを使うには？
前項では、ストレージに入っているWindowsOSのデータをBootloader がメモリに展開してくれることで、いつものWindowsが起動するのでした。
展開するOSをLinuxOSにすれば、あなたがいま使っているPCでもLinuxが直接使えます。
参考ですが、
* Linux OS イメージ
* GRUB (Linux ブート用のBootloader)

の2つを用意すれば、Linuxが起動できるようです。

（↓ LinixOSを展開するイメージ図）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618997/dc991d82-89db-e9a7-ca52-ddd74decca46.png)

実際のPCでは起動時に下図のような表示になって、Ubuntuを選択すればLinuxが、Windowsを選択すればWindowsが立ち上がります。これで2つのOSを使い分けられるデュアルブートPCの完成です！
（よい子はマネしないでください）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618997/b68cb52d-6fc6-be12-5617-3104085ed264.png)

### 仮想化ではないシステムは面倒
とはいえ、いまどきこんな方法でLinux開発をしようとする人はいません。なぜなら不便だからです。
デュアルブートにしたからと言って、2つのOSを同時に使えるわけではありません。WindowsとLinuxを切り替えるたびにPCを再起動しなければなりません。そんな開発環境嫌じゃないですか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618997/60459ed8-94cc-df55-314a-a15fcac3be7c.png)
またWindowsとLinuxではストレージのフォーマット形式が違うため、ストレージに特殊な操作をしてLinux専用の領域を作成する必要があったりします。たとえば、512GBのメモリのうち100GBをLinux専用に割り振ると、Windowsからはその領域は見ることもできなくなります。
このような操作は難しく、下手するとOSが動かなくなるので、初心者がWindowsをぶっ壊すこともあったようです。


というわけで、ここまでで説明したのがいわゆる「仮想化ではないシステム」です。皆さんが普段使っているPCの環境でもありますし、もう少し広義に言うと「PCのメモリに直接LinuxのようなOSイメージを展開することで、OSを使用する」ものです。

## 仮想化とは？
仮想化ではないシステムを見た後なら、下の図の意味がなんとなく分かるかなと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618997/e0a8ac69-5fa5-07ac-43e8-a9d1c715d891.png)

つまり仮想化とは <font color="red">**「ホストOS上に別のOS（ゲストOS ）を載せること」**</font>というわけです。

仮想化の定義がこのようであるので、
* Linuxの上にLinuxを載せる
* Linuxの上にWindowsを載せる
* Macの上にLinuxを載せる

これらすべて仮想化の仲間です（下図）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618997/988b3a7e-3e5f-288b-86cc-282e08ba7590.png)

以上で仮想化とは何か？　についての説明は終了です。ざっくりとでも掴んでいただけたなら幸いです。

# 仮想化の種類
さて、ここまでで「仮想化でないとは何か」「仮想化とは何か」についてイメージできたと思います。
ここからは仮想化について掘り下げていきます。

## 3種類の仮想化技術
仮想化には大きく分けて3種類が存在します。
1. ホストOS型
1. ハイパーバイザ型
1. コンテナ型

それぞれ下図のようなイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2618997/c85f41f2-22ea-6f52-b1fe-3e60b4231a06.png)

1つずつ解説していきます。

### 1. ホストOS型
* __特徴__
    * 先ほどの「仮想化とは？」で説明したイメージと同じもの
    * 仮想マシンが、PCのハード的な動作を仮想的に再現する
    * **ホストOS/ゲストOSの両方が存在する** のが特徴
* __イメージ__
    * ホストOS上に小さなPCをもう一台立ち上げるイメージ
* __例、製品__
    * [Virtual box](https://www.virtualbox.org/)
    * [VMware](https://www.vmware.com/jp/products/workstation-player/workstation-player-evaluation.html)

### 2. ハイパーバイザー型
* __特徴__
    * ハイパーバイザーが、上に乗るOSのコマンドを実行する。
    * __ホストOSが存在しない__
        * ハードウェアが直接ゲストOSを制御できるので、とても高速かつ高性能。
    * 個人で使うにはハードルがとても高い
    * クラウドサービスでよく見かける
* __イメージ__
    * 仮想化専用機。高性能な代わりに扱いが難しい。
* __例、製品__
    * AWS: EC2
    * GCP: Compute Engine
    * Azure: Virtual Machines

### 3. コンテナ型仮想化
* __特徴__
    * __ゲストOSが存在しない__
        * OSが直接動作しないので軽量で高速
        * コンテナエンジンがコマンドを仲介している
    * 簡単便利
    * 一番人気
* __イメージ__
    * コンテナエンジン ≒ 翻訳機
        * コンテナで実行されるコマンドを、コンテナエンジンが変換してホストOSについたえる
        * コマンドはホストOS上で実行され、コンテナは結果だけを得る。
* __例、製品__
    * Docker
    * containerd
    * CRI-O

## Dockerとは？
Dockerとは、コンテナ型仮想化を実現するサービスのことです。
Dockerコマンドを使用することで、コンテナの立ち上げから操作まで、コンテナの実行に必要な一連の機能を含んでいます。
現状は無償版のDockerCEと有償版のDockerEEがリリースされています。
Dockerの仕組みやコマンドについては今後の記事で掘り下げていくので、いったんはこの程度の説明に納めます。

# まとめ
つまり、
* 仮想化：概念レベルの技術
* コンテナ：仮想化の1種で、今最も使われている
* Docker：コンテナ型仮想化を実現するサービス

というイメージです。

ちなみによく`Docker=コンテナ` と言われることがありますが、これはDockerがコンテナ型仮想化のシェアをほぼ独占していたためです。
ただ最近はそうでもないらしく、Dockerコンテナ単体ではなくKubernetesのようなオーケストレーションツールを使う前提が強くなったことで、Containerd や CRI-O などがシェアを伸ばしてきているようです。


## 終わりに
以上で「仮想化とは何か？」についての話は終わりです。
ここまで読んで仮想化についてざっくりとしたイメージを持っていただけたのなら、今後Dockerコンテナを学んでいくうえでの理解のスピードが全然違ってくると思います。
また今後も記事を更新していくので、ぜひご覧ください。

[次回の記事](https://qiita.com/Toyo_m/items/94de894a8558d94b02d1)は、Dockerコマンドの基礎を解説しています。仮想化について理解したあとは、実際のDockerコマンドの理解を深めていっていただけるといいかなと思います。

# 参考資料

* Dockerコンテナの歴史と現状についてとても詳しく書いてありました

https://zenn.dev/ttnt_1013/articles/f36e251a0cd24e

* デュアルブートについて書いてあったサイトです。とても参考になりますが、特に普段使いのPCではマネはしないほうがいいです(経験者)

http://blog.livedoor.jp/pg_dreamer/archives/38331.html


* 仮想化の種類について参考にしました

https://www.itmanage.co.jp/column/virtualization-server-integration/

https://www.designet.co.jp/ossinfo/selection/virtual-infrastructure.html