はじめに
今さらながらコンテナ技術について調べてみました。
というのもKubernetesを使うことになりそうなのですが、コンテナについての知識は単純なdockerの使い方くらいしか知らない状態だったからです。
内容自体はN番煎じですが良い機会?なので、コンテナとは何ぞやというところを見てみたいと思います。
コンテナのにわか知識
まず最初に持っていたコンテナに対するにわか知識ですが、こんな感じ。
- Dockerを使うことで利用できる
- 設定ファイルから開発環境を簡単に構築できる
- 2の開発環境を色々な場所で簡単に再現できる
- 仮想マシンより速くて軽い
これらは実際にDockerを使いながら開発をしている上で感じたことだったり、 ネットで見られる情報だったりして、漠然としたものです。
何で仮想環境より軽いの?とか、仮想環境とどう違うの?とか、そもそもコンテナって? というところは無視して使うだけ使っている状態でした。
なのでこのあたりについて見てみたいと思います。
仮想化について
まず仮想化についてです。仮想マシンを利用したことがある方は多いと思います。
具体的には、VirtualBoxやVMWare等の仮想化ソフトウェアを利用して作る仮想マシンのことです。
例えばホストOS(仮想化ソフトウェアをインストールしているマシン)がWindowsであっても、 仮想マシンの上ではUbuntuを動かすことができ、その環境の中で開発することができたり、 WebサーバやDBサーバなど別マシンとして開発に利用することができたりします。
そんな仮想化ですが、仮想マシンの上でプロセスが動作するイメージは以下です。

ホストOS上の仮想化ソフトウェアの上で仮想マシンが動き、ゲストOS(UbuntuやCentOSなど)が乗り、 その上でプロセスが動いているイメージです。
仮想マシン自体は、ホストOSのリソースが許せば複数起動できるので、複数のマシンを使って 仮想環境でシステムを構築して運用することもできます。
ただ仮想マシンも当然リソースを喰うので、ホストOSの性能が貧弱だと割り当てられるリソースが減ってなかなか使いづらかったりしますね。
仮想化ソフトウェアが動いていて、仮想マシンもリソースを喰って、という状況になるので、どうしても動作が重くなったりはすると思います。
コンテナについて
次にコンテナについてです。こちらも利用したことのある方は多いかと思います。
使い方・使われ方は置いておいて、仮想化に対してプロセスがどう動いているのかというイメージは以下になります。

仮想マシンとの違いとしては、仮想化ソフトウェアが無く、ゲストOSも無いというところかと思います。
ここで結論というかコンテナとは?というところなのですが、
プロセスの実行空間を隔離するための技術
などと言われます。
これはどういうことかと言うと、コンテナ内で動いているプロセスは「ホストOS上の隔離空間内で動いている」ということです。 仮想マシン上のプロセスのように異なるOSの上で動いているのではなく、あくまでホストOSの上で動いている一プロセスです。
??? という感じですが、ここで疑問が出てきます。
ホストの上で動いているという点において、ホストOSがWindowsだった時、「いやコンテナ上でLinuxのアプリ動くんやが?」というものです。
またゲストOSが無いという点について、Dockerを使ったことがある方は以下のようなコマンドを使ったことがあると思います。
$ docker pull ubuntu
思いっきり ubuntu って書いてるけど、ゲストOSが無いとは何だったのか?
これらの疑問について、次に見ていきたいと思います。
疑問点の解消
先の通り、ここまでで以下の疑問が生じました。
- ホストOS上でプロセスが動作しているらしいが、何故異なるOSのプロセスが動くのか
- ゲストOSが存在しないはずだが、
docker pull ubuntuのようなコマンドは何なのか
まずこれらに対する前提と結論を書きます。
前提としてLinux用のプロセスはLinuxカーネルで動作します。
またそれぞれの結論は以下のようになります。
- 例えばホストOSがWindowsの場合、Linuxカーネルを何らかの形で利用している
- コンテナ内には任意のOSが持つファイルシステム(コマンド・ライブラリ等)が収められている
何故そうなっているかというところについては、上で記載しているプロセスが動くイメージをもう少し細かく見ていく必要があります。
コンテナ上のプロセスが動作する細かいイメージ

上の画像内の用語について、少し解説します。
- コマンド
/binや/sbinなどに入っている- Linuxだと
cdとかlsとか
- ライブラリ
/libや/usr/libなどに入っている- OSの標準機能や色々なプログラムから利用されるパーツのまとまり
- カーネル
- OS機能の中核
- メモリ管理やプロセスの管理などHW操作や資源管理などを行う
- OS上で動作するプロセスはカーネルを通してコンピュータを操作する
- プロセスがカーネル機能を呼び出す機構を、システムコールと呼ぶ
プロセス(アプリケーション)は、OSの中核であるカーネル機能を呼び出して動作しています。 例えばファイルの読み込み・書き込みが代表的な動作です。
このI/O機能を実行できるのはカーネルがその機能を持っているからなのですが、アプリケーションなどからこの機能を呼び出すことをシステムコールと言っており、カーネルがシステムコールを処理することでアプリケーションが動作します。
上の図は、この仕組みを図示したものです。
異なるOS上でもアプリケーションが動くのは何故か
Linuxには色々なディストリビューション(UbuntuやCentOS、Debianなど)が存在していることはご存じの方が多いかと思いますが、そのカーネルは共通しています。つまり、個別のアプリケーションを動かすためのライブラリ・コマンドなどのファイルが揃っていれば、異なるディストリビューション上で同じLinuxアプリケーションを動かすことができるということです。
本来Ubuntu上で作成したアプリケーションを、例えばCentOS上で動かそうとすると、環境の違いによって正しく動作させることができません。(debとrpmなどファイル形式も異なったりする)
しかし、CentOS上にUbuntuコンテナ環境を用意すれば、その上でUbuntuで作成したアプリケーションを動かすことができます。 これはコンテナの中にUbuntuアプリケーションを正しく動作させるためのコマンドやライブラリなどが入っていて、Ubuntuのファイルシステムを再現しているためです。
コンテナ内のアプリケーションは、コンテナ内に再現された対象ディストリビューションの環境(ファイルシステム)を利用してシステムコールを行い、システムコールはLinux間で共通のため、狙った動作が正しく行われることになります。

Windows上のコンテナでLinuxアプリケーションが動くのは何故か
上で示した図ですが、Linux上でコンテナを動かしている場合を示していて、Windowsにおいては実際とは異なる図になっています。
Windowsの場合は当然Linuxとカーネルが異なるため、Linuxアプリケーションがシステムコールを呼んでも期待した動作をさせることはできません。
なので、例えばDockerを通してコンテナを使っている場合、Hyper-VやVirtualBoxを使ってLinuxカーネルを仮想化によって再現し、そのカーネルを使うことでLinuxでのコンテナと同じ動作を実現させています。
(例えばDocker for Windowsがありますが、ベースにWSL2とHyper-Vのどちらを使うかを選べるようになっています。これは、ちょっと語弊があるかもですが、どちらを使ってLinuxカーネルを再現しますか?という選択肢になっています)
厳密にはDockerはLinux上でしか動作しないのですが、上にも記載した通り必要なのはLinuxカーネルです。
なのでLinuxカーネルを何らかの形で再現して使えるようにできれば、Windows上でも同じくLinuxコンテナからLinux用のアプリケーションを動かすことができるようになります。

Linuxコンテナとは?
最後に、上の方で書いた、dokcer pull ubuntuの意味です。
ここで言うubuntuは、Ubuntuの環境を再現するために必要なUbuntuに備わっているファイルシステムであり、Ubuntuが持つコマンドやライブラリを指しています。
これがCentOSであれば、中身はCentOSが持つコマンドやライブラリになります。
これらのコマンドやライブラリが異なり、ファイルシステムが異なることは、それぞれを利用したことがある方なら分かるかと思います。
コンテナの中に必要なのは、指定のアプリケーションを動作させるために必要なライブラリであり、カーネルはホストのもの、または仮想的に用意したものを利用します。
このコマンドの「OS名」の部分は、そのOSを再現するためのファイルシステムを指しているということになります。
おわりに
一応、コンテナの概要とDockerを使っていた際に持っていた疑問を解決できたと思います。
ちょっと長くなってしまったので、コンテナを実現している技術については次の記事で書きたいと思います。
ちなみにLinuxコンテナのことばかり書いていますが、Windows用コンテナ技術も存在していますし、Dockerよりも古くからFreeBSDやSolaris等ではコンテナ技術が使われていたりします。
これについても次回で少し触れる予定です。
参考サイト一覧
- https://blog.testrail.techmatrix.jp/containers-are-not-vms/
- https://inokara.hateblo.jp/entry/2017/04/30/092304
- https://hogetech.info/linux/kernel/basic1
- https://www.fenet.jp/infla/column/server/linux%E3%82%AB%E3%83%BC%E3%83%8D%E3%83%AB%E5%85%A5%E9%96%80-4%E3%81%A4%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89%E3%81%A7%E5%BE%B9%E5%BA%95%E8%A7%A3%E8%AA%AC/
- https://linuc.org/study/knowledge/545/
- https://thinkit.co.jp/article/17301
- https://penpen-dev.com/blog/windows-docker-tigai/