目次
こんにちは!ともです(@_tomo_engineer)!
この記事ではDockerの概念的な理解について書きたいと思います。
Dockerを使えば仮想環境を作成し、配布・実行する事が出来ます。
私はVagrantで環境を整備し開発を行っており、こちらでも仮想環境を作成することが出来ます。その違いは何なのか気になったので調べてみました。
参考にした書籍は「プログラマのためのDocker教科書」です。
目次
- 仮想化について
- Dockerとは
仮想化について
仮想化とは、1つのコンピュータ上で仮想的に別のOSを動かす技術の事です。
1つのコンピュータの中に別のコンピュータが存在するという事になります。
仮想的に作られたマシンの環境を仮想環境と呼びます。

仮想環境を作成する利点
サーバ用にもう一台PCが欲しいなと思ってもPCを購入しその後メンテナンスする必要があります。しかし、1つのPC内に仮想化により別のPCを生成出来れば、追加でPCを購入する必要はなくなりますね。またDockerはDockerファイルに設定を記述する事により、それまでは手作業で行われていたインフラの設定をコードで管理する事ができるようになりました。
3つの仮想化技術
現在仮想化の技術は3つあります。
ホスト型仮想化
ホスト型仮想化はホストOS上にゲストOSをインストールします。仮想環境を3つ立ち上げればゲストOSを3つインストールする必要があります。これはオーバーヘッドが大きくなり、無駄なCPUリソース・ディスク容量・メモリ使用量を必要とします。

代表的なホスト型仮想化ソフトウェア:VirtualBox・VMWare
ハイパーバイザー型仮想化
ハイパーバイザー型仮想化はホストOSを必要としません。ハイパーバイザーがハードウェアを直接制御するのでリソースを効率良く使用できます。しかし、仮想環境ごとにOSをインストールするため起動に時間がかかります。

代表的なハイパーバイザー型仮想化:Hyper-V・XenServer
コンテナ型仮想化
コンテナ型仮想化はホスト型・ハイパーバイザ型の仮想化ソフトウェアとは違い、仮想環境のためのOSを必要としません。ホストOS上にコンテナという区画(コンテナ)を作り、コンテナ内にアプリケーションの実行環境を閉じ込めます。これにより、軽量で高速に動作可能です。

代表的なコンテナ型仮想化:Docker
コンテナ仮想化技術
コンテナ仮想化技術を実現するためには、コンテナ毎に機能を閉じ込めなければなりません。これを実現するためnamespace機能を利用し閉じ込めて行きます。
namespace(区切り化)
- PID namespace (プロセスを区別)
- Network namespace (ネットワーク関連の区別)
- UID namespace (ユーザIDの区別)
- MOUNT namespace (どの区画にマウントされたデバイスかの区別)
- UTS namespace (ホスト名・ドメイン名の区別)
- IPC namespace (プロセス間通信の区別)
namespaceにより、あるプロセスがコンテナ1のものなのか、コンテナ2のものなのか区別できるようになります。このように、コンテナ単位であらゆるものを区別する事により区画化を実現する事が出来ます。
cgroup(リソースの管理)
1つのOS上でコンテナが立ち上がるため、各コンテナに資源を割り当てなければなりません。cgroupとはプロセス・スレッドをグループ化し、グループ単位で管理する機能です。namespaceによりプロセス・スレッドはコンテナ毎に区別できるため、コンテナ単位でcgroupで管理を行う事が出来ます。
cgroupではCPUの使用量・メモリやスワップの使用量の割り当てが可能となります。コンテナ1にはCPU使用率の10%を割り当てるという事が可能となり、コンテナ単位で資源の管理を行う事が出来ます。
ネットワーク構成
ネットワークの構成は以下のようになっています。
各仮想環境は物理NICを持ち、それに対応する仮想NICを持っています。
またこれらの仮想NICはdocker0という仮想ブリッジに接続されています。
Dockerを起動すると、172.17.0.0/16のサブネットマスクで各物理NICにIPアドレスが自動的に割り当てられます。

Dockerコンテナ同士の通信
Docker起動時に各コンテナにはIPが自動的に割り振られるため、コンテナ間での通信が可能です。これを実現するのが「リンク機能」となります。IPアドレスにエイリアスを設定し、他のコンテナとの通信を行います。
リンク機能ですが将来的には廃止される可能性があるとご指摘頂きました。代わりにDockerネットワークを作成する事でコンテナ間の通信を行う方法がスタンダードであるようです。Dockerネットワークを作成すればコンテナを名前で発見できるようです。下の記事が参考になります。
Dockerコンテナと外部ネットワークとの通信
DockerではNAPT(Network Address Port Translation)を利用し、1つのグローバルIPアドレスを複数のコンテナで共有しています。これはNAPTのIPアドレスとポート番号との変換機能により実現されています。
まとめ
Dockerがどのような構成になっているのかの概念的な理解を進めました。
他の仮想化方法と違うところは1つのOSをコンテナという単位で分割している所でしたね。今後はDockerの機能について見て行きたいと思います。