コンピューターの進化の歴史から読み解く。プログラムとは翻訳だらけ (6): コンテナ
さて。前回は、仮想マシンについて取り扱いました。1 台のハードウェアで複数の OSを動かすことができるようになりました。それ自身は新しい技術ではなかったですが、PC アーキテクチャの中に搭載され、パフォーマンスが劇的に改善したことで普及しました。
今回は、コンテナについて取り扱います。
コンテナ - アプリケーションの仮想化。OSの軽量な仮想化
仮想マシンによって、x64 コンピューターをファイルとして持ち運びできるようになりました。OS を 100 個立ち上げるのが比較的ですがやりやすくなったわけです。
それでも、その数を考えると課題がありました。それは、特にメモリとストレージが大量に必要になりました。
OS そのものは、メモリを 2GB必要とします。その上でアプリケーションを動かそうと思ったら、4GB は必要ですね。データベースの様にデータを扱うアプリケーションであれば、それでは全然足りません。
つまり、仮想マシンを作るたびに4GB程度のメモリが欲しくなるわけです。100 個動かそうと思ったら、4 GB x 100 で単純に 400 GB!
400GB のメモリーが搭載できる PC があるか分かりませんが😅 Server ならあるかもしれないですね。相当高額だと思います。
そして仮想マシンの仕組みは、本体であるホストOSを稼働させるためにも、メモリーなどが必要です。例えば、先ほどの 100 台の仮想マシンを動かそうと思えば
ホスト OS: 4GB x 1
ゲスト OS: 4Gb x 100
で、合計 404 GBのメモリ。
ゲストOSの数が多いと「まー、いっか」と無視したくなりますが。2,3個だけの場合は、ホストOSの使用するメモリの割合は無視できないですよね。
もっと軽量なものがないか?
OSの軽量な仮想化という点では。
実は殆どの UNIX では、chroot という機能があって、アプリケーションのアクセスできる範囲を、指定したルートディレクトリ以下にしかアクセスできないようにします。
アプリケーションの仮想化という発想。この技術も実は結構前からあるんです。何も新しくありません。同じ OS の上で、複数バージョンの Excel を動かしたい。古い Excel でしか動かないマクロがあるから。みたいなことで、例えば Microsoft App-V のようなものがありました。そのアプリケーションが利用する OSのファイルなどを丸ごとパッケージ化します。App-V では、そのアプリがどんなOSのファイルを使うのかを記録するために、インストールしてある程度操作する、そして、記録を停止する、といった操作を行いました。
Docker
Docker の登場によって、コンテナという言葉とともに OS レベルの仮想化が改善します。
Docker の構造は以下のようになっています。
左側が、仮想マシンですね。Hypervisor の上に、各仮想OSが動いています。WindowsとLinuxという別のOSを動かすことができます。
右側が、コンテナを用いた軽量なOSの仮想化です。Docker の場合は Docker がコンテナエンジンとして各アプリケーションを分離します。OSのカーネルは共有されますが、それ以外は分離されます。
画面の右上の階層ですが… 増えましたねーーー!
皆さんがお気軽に Docker 上にアプリケーションを動かすということは、また翻訳のレイヤーが増えたと言えますね。
Docker の良い点は、とにかく軽量なことです。
こちらは、最も小さいであろう Docker の "Hello World" 的なアプリケーションを稼働させた時のものです。"Pull" とかいって、実はインターネット上の DockerHub から、コンテナ化されているファイル (イメージと言います) をダウンロードしてきています。
なんとサイズが28MB程度! これで十分なんです。
このサイズであれば:
ダウンロードも早い。つまり、ネットワーク上からアプリケーションの入手が早い
使用するメモリも少ない。つまり、1つのコンピューターで大量のアプリケーションの起動ができる
ネットワークの転送が早い。つまり、特定のコンピューターに障害が起こった際に、復旧させるための時間が速くなる
など、いくつもメリットが出てきます。
Docker の更に良い点は、アプリケーションの設定を Dockerfile に詰め込めることです。
以下は docker 公式サイトにあるサンプルです。
FROM node:12-alpine
# Adding build tools to make yarn install work on Apple silicon / arm64 machines
RUN apk add --no-cache python2 g++ make
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
Our Application - Getting Started
1行ずつ、Linux のコマンドです。
これ、実は全ての Docker イメージが持っていて見ることが出来るんです。
Docker には Inspect というコマンドがあります。例えば、Docker Desktop の Images には、ダウンロードあるいは自分で作成 (Build) したイメージの一覧が見えます。そこで、Inspect を選択します。
そうすると Dockerfile での設定が確認できますよね!
Getting Started。なんと16行もありますねー
これは何を意味するか?
コンテナ化する設定をテキストのファイルとして扱える、という事になります。アプリケーションのソースコードも元はテキストファイルで、それをコンパイルして機械語のバイナリーのファイルになります。コンテナも同様で docker build コマンドでバイナリーになります。
面白いのが、バイナリーになるとはいえ、その中でOSのコマンドが実行できますよね。つまり JIT コンパイラーと似たことはできるわけです。自分が動く環境によって、別のコンパイラーをダウンロードする、など、工夫次第でできるわけです。Shell スクリプトには if 文がありますからね。
そして、コンテナ設定をソースコード管理下に置くことが出来ます。これも、アプリケーションと一緒に管理できるわけですよね! GitHub や Azure DevOps などと一緒に CI/CD のパイプラインに組み込むのが容易なんです。
更にもう一つ。Python や Nodeが代表にあげられますが。アプリケーションが参照するライブラリーやパッケージは、どんどんバージョンアップが為されます。この依存関係がとっても複雑で、1つのパッケージがバージョンアップすると途端にライブラリーの依存関係が壊れ、ライブラリーやパッケージがインストールできない事は頻繁に起こります。環境作成だけで1日費やすこともあります😭
コンテナは、瞬間密封みたいな役目も果たします。今、自分の手元で動いた環境。ライブラリーやパッケージ。環境変数なども含めて、丸ごと1つのファイルにします。アプリケーションが確実に動くようにするんです。ちなみにコンテナの中にはアプリケーションのラインタイムも入れちゃいます。Java VMや .NETの CLR。Python のランタイムなどです。
docker hub で Python のイメージの検索をすると、出てきます!
その Tag を見てみると、バージョン管理がなされていますよね!
課題
万能というわけにはいきません。その技術の成立から起こる課題も当然あります。
一番大きいのはOSの違いは越えられません。現在コンテナの主流は Linux です。Linux上で作成したコンテナは別のOS、つまり Windows では動きません。逆もしかりです。
もう一つですが。実はOSのカーネルはコンテナ間で共有されます。つまり、セキュリティやソフトウェア上の問題などがカーネルレベルで発生すると、全てのコンテナに影響が出ます。ベースのOSをしっかりと管理する必要があるということですね。
まとめ
ここまで 6回にわたって、CPUの登場からコンテナまでを扱ってきました。階層の図も、最後にはこんな縦長になりましたね。
こんなに縦長でもさして問題がないのはなぜか? ひとえに今も継続される技術革新にあります。ハードウェアは常に小型化・軽量化・省電力化が図られているんです。Intel / AMD 型のCPUに加えて、Apple社が M1という新しいARMベースのCPUを提供しています。CPUが違いますよね? ということは…
ここまでお読みいただいた皆さんなら、皆さんのアプリケーションを動かすために何を追加でする必要があるのかお解りいただけると思います。
ソフトウェアは実は翻訳の世界です。そのための翻訳のソフトウェアをコンパイラーと言います。
Microsoft という会社は Windows に代表される OSの会社と思われていることが多いです。実は、その創業はコンパイラーのソフトウェアなんです。
この紙みたいなもの。何だと思われますか?
COVID-19 が落ち着いたら、是非その歴史的瞬間を振り返るために Microsoft の Visitor Center に行く機会を作ってみてください。
私は何度も行って毎回このテープを見て毎回一人で感動しています😊