Docker 概要

Docker はアプリケーションの開発、導入、実行を行うためのオープンなプラットフォームです。 Docker を使えば、アプリケーションをインフラストラクチャーから切り離すことができるため、ソフトウエアをすばやく提供することができます。 Docker であれば、アプリケーションを管理する手法をそのまま、インフラストラクチャーの管理にも適用できます。 Docker が採用する方法を最大限利用して、アプリケーションの導入、テスト、コードデプロイをすばやく行うことは、つまりコーディングと実稼動の合間を大きく軽減できることを意味します。

Docker プラットフォーム

Docker はアプリケーションをパッケージ化して実行するために、ほぼ分離された環境 [1] となるコンテナというものを提供します。 隔離してセキュリティを保つことから、実行するホスト上に複数のコンテナを同時に実行することができます。 コンテナは非常に軽量なものとなります。 なぜならハイパーバイザーを別途ロードする必要などなく、ホストマシンのカーネルを使って動作するからです。 このことは手元にあるハードウェアの中から、必要なものを使ってより多くのコンテナが実行できることを意味します。 それは仮想マシンを使う以上のことです。 さらに Docker コンテナを動作させるホストマシンは、それ自体が仮想マシンであっても構わないのです。

Docker が提供するのは、コンテナのライフサイクルを管理するツールとプラットフォームです。

  • コンテナを利用して、アプリケーションとそれをサポートするコンポーネント [2] を開発します。
  • コンテナは、アプリケーションの配布とテストを行う1つの単位となります。
  • 準備ができたら本番環境に向けてアプリケーションをデプロイします。デプロイの単位は、1つのコンテナか、あるいはオーケストレーション(orchestrated [3] )された1つのサービスです。その本番環境があたかも手元のデータセンタ上であったり、クラウドプロバイダ上であったりするのと同様に動作します。

訳者注

[1]隔離された環境とは "isolated environment" の訳。隔離されて離された環境というよりも、部屋の中を仕切るようなイメージが近いです
[2]このコンポーネントとは、Docker をとりまく各種ツール群やサービスです
[3]原文は "orchestrated service" 。複数台のサーバ上で、サービスを一斉かつ自動的に制御する動作です

Docker Engine

Docker Engine は、主に以下の3つのコンポーネントからなるクライアントサーバ型アプリケーションです。

  • サーバ。長時間稼動する種類のプログラムでありデーモン・プロセスと呼ばれる( dockerd コマンド)。
  • REST API。プログラムとデーモンとの間での通信方法を定義し、何をなすべきかを指示する。
  • コマンドライン・インターフェース(command line interface; CLI)クライアント( docker コマンド)。
Docker Engine コンポーネント図

CLI は Docker REST API を通じて、スクリプトや直接のコマンド実行により Docker デーモンを制御したり入出力を行ったりします。 Docker アプリケーションの多くが、基本的なところで API や CLI を利用しています。

デーモンは Docker オブジェクトを作成、管理します。 Docker オブジェクトとは、イメージ、コンテナー、ネットワーク、データ・ボリュームなどです。

注釈

Docker は、オープンソース Apache 2.0 ライセンスのもとで提供されています。

Docker の詳細については、 Docker のアーキテクチャ を参照してください。

何のために Docker を使うのか?

アプリケーションの配信をすばやく一貫性を保って

Docker は開発のライフサイクルを効率化します。 開発するアプリケーションやサービスがローカルなコンテナ内に実現でき、開発者は標準化された環境により作業が進められるからです。 コンテナを使った開発は、継続的インテグレーション (continuous integration; CI) や継続的開発 (continuous development; CD) のワークフローに適しています。

以下のようなシナリオ例を考えてみてください。

  • 開発者がローカルでコードを書き、仲間とその作業を共有するために Docker コンテナを使います。
  • Docker によりアプリケーションをテスト環境に投入し、自動および手動のテストを実行します。
  • 開発者がバグを発見したら、開発環境においてこれを修正して、アプリケーションをテスト環境に再デプロイし、テスト確認を行ないます。
  • テストが完了します。この後にユーザが修正版を利用できるようにすることは、更新済イメージを本番環境へ投入することと同じく容易なことです。

迅速なデプロイとスケーリング

Docker によるコンテナベースのプラットフォームは、処理負荷の高度な分散を考慮しています。 Docker コンテナは、開発者のノートパソコン上で実行できるだけでなく、データセンタの物理マシンや仮想マシン、クラウドプロバイダ、そしてさまざまな環境の組み合わせにおいて実行可能です。

Docker の可搬性と軽量な特性は、以下のようなことを容易に実現します。 それは処理負荷を動的に管理できること、ビジネスシーンでの要求に応じてアプリケーションのスケールアップや提供終了を簡単に、しかもほぼリアルタイムで行うことができます。

同一ハードウェア上にて負荷の高い処理を実行

Docker は軽量かつ高速です。 ハイパーバイザ・ベースの仮想マシンに取って変わる、実用的で費用対効果の高いものです。 したがってコンピュータ性能をフルに活用してビジネス目標を達成できます。 Docker は高度に処理集中する環境に適しており、さらには中小規模の、より少ないリソースの中でのシステム構築にも適しています。

Docker のアーキテクチャ

Docker はクライアント・サーバ型のアーキテクチャを採用しています。 Docker クライアント は Docker デーモンに処理を依頼します。 このデーモンは、Docker コンテナの構築、実行、配布という複雑な仕事をこなします。 Docker クライアントとデーモンは同一システム上で動かすことも 可能 ですが、別のシステム上であっても、Docker クライアントからリモートにある Docker デーモンへのアクセスが可能です。 Docker クライアントとデーモンの間の通信には REST API が利用され、UNIX ソケットまたはネット・ワークインターフェイスを介して行われます。

Docker アーキテクチャ図

Docker デーモン

Docker デーモン( dockerd )は Docker API リクエストを受け付け、イメージ、コンテナ、ネットワーク、ボリュームといった Docker オブジェクトを管理します。また、Docker サービスを管理するため、他のデーモンとも通信を行います。

Docker クライアント

Docker クライアント( docker )は Docker とのやりとりを行うために、たいていのユーザが利用するものです。 docker run のようなコマンドが実行されると、Docker クライアントは dockerd にそのコマンドを伝えます。 そして dockerd はその内容を実現します。 docker コマンドは Docker API を利用しています。 Docker クライアントは複数のデーモンと通信することができます。

Docker レジストリ

Docker レジストリは Docker イメージを保管します。 Docker Hub と Docker Cloud は公開レジストリであり、誰でも利用可能です。 また Docker はデフォルトで Docker Hub のイメージを探すよう設定されています。 独自にプライベート・レジストリを運用することもできます。 もし Docker データセンタ(Docker Datacenter; DDC)を利用するのであれば、Docker トラステッド・レジストリ(Docker Trusted Registry; DTR)が含まれています。

docker pulldocker run コマンドを使うと、設定されたレジストリから必要なイメージを取得します。 docker push コマンドを使えば、イメージを指定したレジストリに送信します。

Docker ストア を利用すれば Docker イメージの売買や無償配布ができます。 たとえば、ソフトウェア・ベンダが提供するアプリケーションやサービスを含んだ Docker イメージを購入し、そのイメージを使って、テスト、ステージング、本番の各環境にアプリケーションをデプロイすることができます。アプリケーションを更新するには、もう一度イメージの新バージョンを取得し、コンテナを再デプロイすれば実現できます。

Docker オブジェクト

Docker の利用時は、イメージ、コンテナ、ネットワーク、ボリューム、プラグインや、その他のオブジェクトを作成・利用します。このセクションは各オブジェクトの概要を説明します。

イメージ

イメージ( image )とは、Docker コンテナを作成する命令が入った読み込み専用のテンプレートです。 通常イメージは、他のイメージをベースにしてそれをカスタマイズして利用します。 たとえば ubuntu イメージをベースとするイメージを作ったとします。 そこには Apache ウェブ・サーバや自開発したアプリケーションといったものをインストールするかもしれません。 さらにアプリケーション実行に必要となる詳細な設定も加えることにもなるでしょう。

イメージは作ろうと思えば作ることができ、他の方が作ってレジストリに公開されているイメージを使うということもできます。 イメージを自分で作る場合は Dockerfile というファイルを生成します。 このファイルの文法は単純なものであり、そこにはイメージを生成して実行するまでの手順が定義されます。 Dockerfile 内の個々の命令ごとに、イメージ内にはレイヤというものが生成されます。 Dockerfile の内容を書き換えたことでイメージが再構築されるときには、変更がかかったレイヤのみが再生成されます。 他の仮想化技術に比べて Dockerイメージというものが軽量、小さい、早いを実現できているのも、そういった部分があるからです。

コンテナ

コンテナとは、イメージが実行状態となったインスタンスのことです。 コンテナに対する生成、実行、停止、移動、削除は Docker API や CLI を使って行われます。 コンテナは、複数のネットワークへの接続、ストレージの追加を行うことができ、さらには現時点の状態にもとづいた新たなイメージを生成することもできます。

デフォルトでは、コンテナは他のコンテナやホストマシンとは、程よく分離されています。 コンテナに属するネットワーク、ストレージ、基盤となるサブシステムなどを、いかにして他のコンテナやホストマシンから切り離すか、その程度は制御することが可能です。

コンテナはイメージによって定義されるものです。 またこれを生成、実行するために設定したオプションによっても定義されます。 コンテナを削除すると、その時点での状態に対して変更がかかっていたとしても、永続的なストレージに保存されていないものは消失します。

``docker run`` コマンドの例

次のコマンドは ubuntu コンテナを実行し、ローカルのコマンドライン処理のセッションを結びつけます。そして /bin/bash を実行します。

$ docker run -i -t ubuntu /bin/bash

このコマンドを実行すると、以下が発生します(レジストリから入手した際のデフォルトの設定を使用しているものとします)。

  1. ubuntu イメージがローカルになければ、Docker は設定されているレジストリからイメージを取得します。この動作は手動で docker pull ubuntu を実行するのと同じです。
  2. Docker は新しいコンテナを生成します。これは手動で docker create コマンドを実行することと同じです。
  3. Docker はコンテナに対して読み書きが可能なファイルシステムを割り当てます。これが最終的にレイヤとなります。このことによりコンテナの稼動中に、ローカルなファイルシステム内でのファイルやディレクトリの生成や変更などが実現されます。
  4. Docker はネットワーク・インターフェースを生成し、コンテナをデフォルト・ネットワークに接続します。ここではネットワーク・オプションを指定していないものとしているためです。このときには、コンテナに対しての IP アドレスの割り当ても行われます。デフォルトでコンテナは、ホストマシンのネットワーク接続を利用して、外部ネットワークに接続します。
  5. Docker はコンテナを起動し、 /bin/bash を実行します。( -i-t のフラグにより)対話的に、かつターミナル画面に接続するようにして実行しているため、手元のキーボードを使って入力することができ、ターミナル画面に出力が行われるようになります。
  6. exit を入力すると、 /bin/bash コマンドは終了します。コンテナは停止状態となりますが、削除はされません。コンテナを再起動したり削除することもできます。

サービス

サービスは、複数の Docker デーモンにわたって、コンテナのスケール変更ができるようにします。 複数のデーモンはスォームと呼ばれるものとして扱われ、複数のマネージャ、ワーカとともに動作します。 そしてすべてのデーモンが Docker API を利用して通信します。 サービスは必要となる状態を定義することが可能であり、たとえばサービスのレプリカ数を、指定した時間においてどれだけ作り出すかを定義できます。 デフォルトでは、すべてのワーカ・ノードにわたって負荷分散が行われます。 利用者からすると、Docker サービスは1つのアプリケーションとして見えます。 Docker Engine がスウォームモードをサポートするのは Docker バージョン 1.12 またはそれ以上です。

基盤とする技術

Docker は Go 言語 で書かれており、Linux カーネルの機能をうまく活用して、さまざまな機能性を実現しています。

名前空間

Docker は名前空間という技術を利用して コンテナ と呼ぶ作業空間を分離して提供します。 コンテナが実行されたとき、Docker はそのコンテナに対して複数の 名前空間 を生成します。

名前空間はいくつもの分離状態を作り出します。 コンテナ内のさまざまな処理は、分離された名前空間内にて実行され、それぞれへのアクセスはその名前空間内に限定されます。

Docker Engine が取り扱う名前空間は、Linux 上で言えば以下のようなものです。

  • pid 名前空間 :プロセスの分離。(PID:プロセス ID)
  • net 名前空間 :ネットワーク・インターフェースの管理。(NET:ネットワーキング)
  • ipc 名前空間 :IPC リソースに対するアクセス管理。(IPC:InterProcess Communication、内部プロセスの通信)
  • mnt 名前空間 :ファイルシステムのマウント・ポイントの管理。(MNT:マウント)
  • uts 名前空間 :カーネルとバージョンの分離。(UTS:Unix Timesharing System、Unix タイムシェアリング・システム)

コントロール・グループ (Control groups)

Linux 上で動作する Docker Engine には、さらに コントール・グループcgroups; control groups)と呼ばれる技術も併用されます。 cgroup は、アプリケーションが利用するリソースを特定のものに限定します。 つまりコントロール・グループは、Docker Engine が利用可能なハードウェア・リソースをコンテナ間で共有するようにし、必要に応じて利用上限や制約をつけることも行います。たとえば特定のコンテナが利用するメモリの上限を設定することもできます。

ユニオン・ファイル・システム

ユニオン・ファイル・システムは UnionFS というものであり、レイヤが作り出され、軽量かつ高速に処理が行われるファイルシステムのことです。 Docker Engine は UnionFS を利用して、コンテナにおけるブロックを構築します。 Docker Engine では AUFS、btrfs、vfs、DeviceMapper などの UnionFS 系のファイルシステムも利用できます。

コンテナ・フォーマット

名前空間、コントロール・グループ、UnionFS は Docker Engine により、コンテナ・フォーマットと呼ばれるラッパーとして構成されます。 このコンテナ・フォーマットのデフォルトが libcontainer です。 いずれ BSD Jail や Solaris Zone などを技術統合した新たなコンテナ・フォーマットがサポートされることになるかもしれません。

次のステップ

参考

Docker overview | Docker Documentation
https://docs.docker.com/engine/docker-overview/