コンテナについて解説します。
目次
コンテナの仕組み
コンテナはホストOSのリソースを論理的に分離して、アプリケーションを動かすために必要なライブラリやアプリケーションを一つにまとめて動かせるようにした技術です。コンテナはホストOSのプロセスの一つであり、実行時にプロセスの属性を変更することで、ホストOS上で仮想環境を構築することができます。
コンテナの実行
コンテナアプリケーションは環境の設定をyaml形式のファイル内で記述します。これによりコンテナアプリケーションの実行環境さえ用意できれば、ホストOSに依存せず同じ環境を簡便に立ち上げられます。また仮想化と異なりコンテナではゲストOSの立ち上げが不要なため、環境立ち上げにかかる時間も仮想化よりもはるかに速くなります。一方で仮想化に比べるとリソースの分離レベルが低く、セキュリティ面やパフォーマンス面で同一ホストOS上で動いているアプリケーションに対して与える影響やリスクもあります。
コンテナイメージの共有

コンテナでは環境構築にあたって、コンテナイメージと呼ばれる環境の構成がネット上で数多く公開されています。公式のDockerレジストリであるDocker HubではOS環境やDB環境など、様々なレイヤーのコンテナイメージが配布されています。これらのイメージは独自でカスタマイズしてプライベートなレジストリ上で共有することも可能です。コンテナという名前が意味するように、IT技術におけるコンテナもファイル形式での再配布を容易にすることで、開発者のサーバー運用コストを大きく削減することに成功しています。
コンテナのメリット
高速な動作
仮想化がホストOSやハイパーバイザー上に新たなゲストOSを立ち上げるのに対し、コンテナはホストOS上で動作するため動作が速く軽くなります。特にアプリケーションのデプロイを継続的に行う上で、環境が立ち上がるまでの時間はシステム運用担当者の大きなボトルネックとなっていました。コンテナはその軽快な動作により、その課題解決に大きな貢献を果たしています。
コンテナと仮想化の違いはこちら
実行環境に依存しない
コンテナは実行環境に依存せず、誰がどこで立ち上げても同じ動きをします。コンテナを使って開発を行えば、ローカル環境の違いによる設定や、本番環境を考慮したデプロイ作業などが大幅に楽になります。これは組織開発を行う上でデバイス間での環境格差、開発環境と本番環境の違いを無くすメリットとなります。
ローカル環境に影響を与えない
コンテナ内で環境に変更を加えたとしても、ローカルの設定に影響を与えることはありません。実験的に環境を試してみたいけど、ローカルの依存関係に変更を加えたくない時には、コンテナ環境をサンドボックスとして環境設定を自由に変更したり、環境を元に戻したい場合はコンテナ単位で削除することもできます。
バージョン管理が容易になる
アプリケーションが動く環境そのものをコンテナイメージとして管理することで、バージョンの更新による依存関係のインストール作業が容易になります。
コンテナ技術の歴史
コンテナ技術以前
仮想化
コンテナ技術以前の世界では、余っているコンピューターリソースを有効活用する手段として「仮想化」という技術が主流でしたが、仮想化技術は高性能な物理サーバーを用意する必要があり、気軽に使えるものではありませんでした。
クラウド
クラウドの登場によって、高性能な物理サーバーを用意しなくても、すぐに立ち上げたり、停止できるクラウドサーバーが主流になります。しかし、最小単位がサーバーのインスタンスとなるため、無駄なリソースは一定発生してしまします。
コンテナ
コンテナ技術によって、同一のサーバーのインスタンスの中でもさらに機能を分割して有効活用することができるようになりました。現在ではコンテナが、リソースを分配する際の最小単位として扱われています。
Dockerとコンテナ
Docker
コンテナにはDockerという技術が多く使われます。
まず、Dockerfileというものにアプリケーションの設定や、実行環境を整えるための設定を全て書きます。続いて、Dockerfileをビルドしてdocker imageというファイルにまとめます。docker imageはコンテナの設計図のようなもので、docker imageを使って実際にアプリケーションが動くコンテナを立ち上げます。dockerを使った開発ではdocker imageをpullして、それぞれの環境でコンテナを立ち上げます。
docker-compose
docker-composeは複数のdockerコンテナ間の通信を設定できるツールです。
dockerを使った開発では、1つのコンテナで全てを完結させるのではなく、複数のコンテナを組み合わせて1つのアプリケーションを作っていくことがあります。例えば、Nginxプロキシ、railsサーバ、MySQLデータベースを使ったAPIサーバを立ち上げるとします。この場合、Nginxコンテナ、Railsコンテナ、MySQLコンテナを立ち上げて、それぞれのコンテナ間をnetworkで連携させてアプリケーションを構築します。この時に活躍するのがdocker-composeです。
コンテナオーケストレーション
コンテナオーケストレーションとは、多数のコンテナに対する運用管理作業行うためのツールです。
kubernetes
kubernetesは、クラスターという全体リソースの中でPodという「複数のdockerコンテナの塊」を適切にスケーリングしてくれる技術です。ギリシャ語で「司令塔」を意味しています。
クラスターは複数のnode(1台のインスタンス)を合体させて作る巨大なリソースのことで、その中でkubernetesが適切にPodを配置します。例えば、Nginxコンテナ、Railsコンテナの2つが入っているPodがあって、通常は1つのPodでリクエストを捌けていますが、アプリケーションへのトラフィックが集中したタイミングで、アプリケーションがリクエストに対応できなくなったとします。この時、kubernetesは自動的にPod数を増やすことによって、リクエストを捌けるインフラを維持してくれます。そしてリクエストが落ち着いたら元のPod数に戻します。
コンテナの使い方
infrastructure as code
アプリケーションを動かすためには、システムそのものの開発以外に、そのアプリケーションが動作する依存関係などのインフラを整える必要があります。例えばRailsのAPIサーバーを作ろうと思った時は、そもそも実行環境にrailsをインストールする必要があります。 dockerを使えば、このような「アプリケーションを動かすためにいつも手動でやっていた面倒な作業」をDockerfileの中にコードとして書き記すことができます。
docker imageからコンテナを作れば「READMEにしたがってインストールしたが、動かなくなった」ということも無くなります。
docker-composeでサーバを立ててみる
実際にdocker-composeを使ってnode.jsのサーバーを立ててみましょう。まずはdockerとdocker-composeというツールをローカル環境にインストールします。
コンテナの設定


docker-compose.yml
src/
index.js
package.json
のファイル構成を作ります。
src以下にはnode.jsで動かしたいサーバのJSファイルを置いておきます。ここは自由に編集してください。ルートディレクトリにあるdocker-compose.ymlというファイルにDockerコンテナを立ち上げるための設定を書いていきます。通常はDockerfileを自分で書いてビルドする必要がありますが、今回はnode.jsのイメージをそのまま使うので、それをdocker-comoose.ymlで指定します。
docker.compose.yml
version: '3'
services:
node:
image: library/node
container_name: test
volumes:
- ./src:/src
working_dir: "/src"
command: "node index.js"
ここでは、library/nodeイメージをもとにしたコンテナを、nodeという名前で立ち上げるための設定が書かれています。node.jsが動作するためのファイルボリュームとしてsrc以下を指定しています。commandで実際にコンテナの中でindex.jsが起動するようにしています。
コンテナを立ち上げる

docker-compose up
コマンドを使ってコンテナを立ち上げることができます。
まとめ
コンテナはクラウド技術の普及において、システム運用のあり方を大きく変化させました。特に昨今のサービスではWebブラウザ、スマートフォンアプリケーション、IoTなど、複数の環境にまたがってサービス提供を行うケースも増してきており、システム運用担当者はこれまで以上にサーバー運用の柔軟性や高速化を求められます。コンテナはそのような時代背景において、技術の依存関係をパッケージにまとめることで、世に広く普及しました。システム開発を行う上でも、システムの依存関係は避けては通れない道であることからも、開発者にとってコンテナはすでに必要不可欠な技術となりつつあります。