前人未踏の領域へ アプリ開発編

Android, iOSアプリ開発に関する調査メモ置き場。ほとんどAndroid。はてなダイアリーから移行したため古い記事にはアプリ以外も含まれます。

Dockerを理解する

以下の公式サイトの記事を読みつつ日本語訳。全体的に理解が怪しいので日本語も怪しくなってます。
https://docs.docker.com/introduction/understanding-docker/

Dockerを理解する

Dockerはアプリを開発、出荷、そして実行するためのオープンプラットフォームです。Dockerはアプリケーションを素早く配信するためにデザインされています。Dockerによってアプリがインフラから分離され、アプリを管理するかのようにインフラを扱うことができます。Dockerはコードの出荷を早くするのを助け、テストを早くし、配備を早くし、コードの記述のコードの実行のサイクルを短くします。

Dockerはワークフローで軽量コンテナを仮想化プラットフォームと結びつけ、そしてアプリの管理と配備を助けるツールを使うことによってこれを行います。

その中心はDockerがほとんどどのアプリでもコンテナ内で安全に分離されて実行する方法を提供することです。その分離とセキュリティはホスト上で同時に多くのコンテナを実行することができます。その軽量なコンテナの性質は別途ハイパーバイザーをロードすることなしに実行され、ハードウェアからさらに多くのものを得ることを意味します。

コンテナ仮想化の周辺には幾つかの方法であなたを助けるツールとプラットフォームがあります。

  • Dockerコンテナ内にアプリケーションを入れる。
  • 開発とテストの促進のためにこれらのコンテナをあなたたちのチームに行き渡らせる。
  • ローカルデータセンターまたはクラウド内であろうと、製品環境にそれらのアプリケーションを配備する。

Dockerを何のために使えるの?

アプリの素早い配送

Dockerは開発のライフサイクルを助けるのに完璧です。Dockerは開発者達にアプリやサービスを含むローカルコンテナ上での開発を可能にします。それは連続的な結合と開発のワークフローを統合します。
例えば、開発者がローカルにコードを記述し、それらの開発スタックをDockerを通じて彼らの同僚にシェアします。準備ができたときに、テスト環境で開発中のコードとスタックをプッシュし、要求されるどんなテストでも実行します。テスト環境では、あなたはDockerのイメージを本番にプッシュし、コードをデプロイできます。

配備と拡張をより簡単に

Dockerのコンテナベースのプラットフォームは高い移植可能なワークロードを持ちます。Dockerコンテナは開発者のローカルホスト上でも、データセンター内の物理または仮想マシンでも、あるいはクラウド上でも動作します。
Dockerの移植性と軽量な性質はまた動的なワークロードの管理も簡単にします。Dockerを使ってアプリやサービスを素早くスケールアップをしたり、ダウンさせることができます。Dockerのスピードはリアルタイムに近いスケーリングができることを意味します。

高密度でより良いワークロード実行の達成

Dockerは軽量で高速です。それはハイパーバイザーベースのVMに対して実行可能でコスト効率が高い代替手段を提供します。これは特に高密度な環境で役に立ちます。例えば、自身のクラウドやPaaSなどです。しかしまた、所有するリソースからさらに多くのものを得たいところでは、小、中規模の開発でも役に立ちます。

Dockerの主要コンポーネントとは?

Dockerは2つの主要コンポーネントを持ちます。

  • Docker: オープンソースのコンテナ仮想化プラットフォーム
  • Docker Hub: Dockerコンテナをシェア、管理するための我々のSaaSプラットフォーム

DockerはApache2.0でライセンスされています。

Dockerのアーキテクチャとは?

Dockerはクライアント/サーバー型アーキテクチャを使用しています。DockerクライアントはDockerデーモンと会話し、Dockerコンテナの構築、実行、配送といった重労働を行います。Dockerクライアントとデーモンの両方は同じシステム上で動作するか、リモートのDockerデーモンと接続することもできます。そのDockerクライアントとサービスはソケットもしくはRESTful APIを通じて通信します。
https://docs.docker.com/article-img/architecture.svg

Dockerデーモン

上記のように、Dockerデーモンはホストマシン上で動作します。ユーザーはデーモンとは直接対話せず、代わりにDockerクライアントを通じて対話します。

Dockerクライアント

Dockerクライアントは"docker"というバイナリファイル形式の実行ファイルです。主にDockerとの対話に使用されます。ユーザーからのコマンドを受け入れ、Dockerデーモンとの間をコミュニケートします。

Docker内部

Docker内部を理解するために、以下の3つのコンポーネントを知る必要があります。

  • Docker Images
  • Docker registries
  • Docker containers

Docker Images
Dockerイメージは読み取り専用のテンプレートです。例えば、ApacheとあなたのアプリがインストールされたUbuntu OSをイメージに含めることができます。イメージはDockerコンテナを作るために使われます。Dockerは新しいイメージの作成や既存のイメージの更新のために単純な方法を提供しています。あるいは他の人がすでに作成したDockerイメージをダウンロードすることができます。DockerイメージはDockerのビルドコンポーネントです。
Docker registries
Dockerレジストリはイメージを保持します。これらはあなたがイメージをダウンロード、アップロードする場所に、パブリックまたはプライベートに格納します。パブリックなDockerレジストリDocker Hubと呼ばれます。それはあなたが使用するための既存のイメージの巨大なコレクションを提供します。これらはあなた自身で作成したイメージを作ることもでき、誰かが以前に作成したイメージを使うこともできます。DockerレジストリはDockerのディストリビューションコンポーネントです。
Docker containers
Dockerコンテナはディレクトリに似ています。Dockerコンテナはアプリケーションの実行に必要なすべてを保持します。それぞれのコンテナは以前に作成したDockerイメージから作られます。Dockerコンテナは実行、開始、停止、移動、そして削除ができます。それぞれのコンテナは隔離された安全なアプリケーション環境です。DockerコンテナはDockerの実行コンポーネントです。

で、Dockerはどのように動く?

今のところ、我々は以下を学びました。

  1. アプリケーションを持ったDockerイメージを作ることができます。
  2. アプリを実行するためのDockerイメージからDockerコンテナを作ることができます。
  3. DockerイメージをDoker Hubか自身のレジストリを通じてシェアすることができます。

これらの3つの要素がどのように違いに連動してDockerを動作させるか見てみましょう。

Dockerイメージはどう動く?

我々はすでにDockerイメージが、Dockerコンテナから起動されるための読み取り専用のテンプレートであることを見てきました。それぞれのイメージはレイヤーの連続から成ります。Dockerは1つのイメージにこれらのレイヤーを結合するためにUnionファイルシステムを使用します。Unionファイルシステムは分離されたファイルシステムからなるファイルとディレクトリを許し、ブランチとして知られる、透過的に重ねられ、1つのまとまったファイルシステムを形成します。
Dockerがこんなにも軽量である理由の1つは3つの層にあります。Dockerのイメージを変更する時、(例えばアプリを新しいバージョンに更新するなど) 新しいレイヤーが構築されます。従って、イメージ全体を置き換えるか、バーチャルマシンでやるように全体を再構築するよりも、レイヤーが追加されるか、更新されるだけで済みます。今や新たにイメージ全体を配布する必要はなく、ただ更新し、配布用のDockerイメージを素早くシンプルに作成します。
すべてのイメージはベースイメージから始まります。たとえばUbuntuイメージのベースとなるubuntu、あるいはFedoraイメージのfedoraなど。また新しい基盤として自身のイメージを使うこともできます。例えば、Apacheベースイメージを持っている場合、すべてのWebアプリケーションのイメージの基盤として使うことができます。

Dockerは通常、Docker Hubからこれらの基盤イメージを取得します。
Dockerイメージは次にこれらの基盤イメージを、我々が指示書(instructions)と呼ぶ単純で記述的なステップの一式を使って構築されます。それぞれの指示書はイメージの新しいレイヤーを生成します。指示書は以下のように動作します。

  • コマンドの実行
  • ファイルまたはディレクトリの追加
  • 環境変数の生成
  • このイメージからコンテナが起動されたときにどのプロセスで実行するか

これらの指示書はDockfileと呼ばれるファイルに格納されます。あなたがイメージの構築をリクエストしたときmDockerはこのDockfileを読み込み、指示書を実行し、最終的なイメージを返します。

Dockerレジストリはどう動く?

DockerレジストリはDockerイメージのための貯蔵所です。一度Dockerイメージを構築したら、それをパブリックレジストリであるDocker Hubかあるいは自身のファイアウォール内にあるレジストリにプッシュすることができます。
Dockerクライアントを使うことで、すでに公開されているDockerイメージを検索し、それらをプルして、そこからコンテナをビルドするためにあなたのDockerHostにダウンロードすることができます。
Docker Hubはパブリックとプライベートの両方を提供しています。パブリックストレージは検索可能で、誰でもダウンロードできます。プライベートストレージはあなた自身とあなたのユーザーの検索結果にだけ含まれ、イメージをダウンロードし、コンテナを作成することができます。こちらから登録できます

コンテナはどう動く?

コンテナはOSとユーザーが追加したファイル、そしてメタデータから構成されます。それぞれのコンテナはイメージから作成されます。イメージはコンテナが何を持ち、どのプロセスを実行しいつ起動されるか、そして様々な設定データをDockerに伝えます。Dockerイメージは読み取り専用です。Dockerがイメージからコンテナを実行すると、あなたのApplicationが次に実行できるイメージ(Unionファイルシステムによって)の先頭部分に読み書き可能なレイヤーが追加されます。

コンテナ実行時には何が起きる?

dockerバイナリもしくはAPIを通じてDockerクライアントはDockerデーモンにコンテナの実行を伝えます。

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

このコマンドを見ていきましょう。Dockerクライアントはdockerバイナリを使って起動され、新しいコンテナを起動するためにrunオプションが付いています。Dockerクライアントは最低でもDockerデーモンにコンテナを実行するために伝えなければいけないことがあります。

  • どのDockerイメージでコンテナを構築するか。ここではUbuntuの基盤イメージであるubuntuを使っている
  • コンテナが起動した際にその内部で実行させたいコマンド。ここではコンテナ内でBashシェルを開始したいので/bin/bashとなる

このコマンドを実行したら何が起きる?
順番に、Dockerは以下を実行します。

  • ubuntuイメージをプルする:Dockerはubuntuイメージの存在をチェックし、ローカルに存在しなければDocker Hubからダウンロードする。もしイメージがすでに存在すればDockerは新しいコンテナのためにそれを使用する。
  • 新しいコンテナを生成する:一度Dockerがイメージを作ると、コンテナを生成するために使用される。
  • ファイルシステムを割り当て、読み書き可能なレイヤーにマウントする:コンテナはファイルシステム内で生成され、イメージに読み書き可能なレイヤーが追加される。
  • ネットワーク/ブリッジインターフェースの割り当て:Dockerコンテナにローカルホストとの通信を許可するためにネットワークインターフェースが生成される。
  • IPアドレスの設定:プールから利用可能なIPアドレスを見つけ、割り当てる。
  • 指定されたプロセスを実行する:アプリケーションを実行するなど。
  • アプリケーションのアウトプットをキャプチャし、提供する:アプリがどのように動作しているかを見るために、接続し、標準入力と出力とエラーをログに書き出す。

あなたは今やコンテナを実行しています!ここからはコンテナを管理し、アプリケーションと対話し、それから終了したら停止しコンテナを削除することができます。

基盤となる技術

DockerはGo言語で記述され、これまで見てきた機能性を提供するためにいくつかのLinuxカーネル機能を使用しています。

名前空間

Dockerは我々がコンテナと呼んでいる分離されたワークスペースを提供するために名前空間(namespace)と呼ばれる技術を利用しています。コンテナの実行時、Dockerはコンテナのために名前空間のセットを生成します。
これは隔離されたレイヤー:それぞれのコンテナが自身の名前空間内で実行されその外へのアクセスができない状態 を提供します。
Dockerが使用する名前空間の幾つかは次の通りです。

  • pid : プロセス分離のために使用(PID:Process ID)
  • net : ネットワークインターフェース管理のために使用(NET:Networking)
  • ipc : IPCリソースへのアクセス管理のために使用(IPC: InterProcess Communication)
  • mnt : マウントポイント管理のために使用(MNT: Mount)
  • uts : バージョン識別とカーネル隔離のために使用(UTS: Unix Timesharing System)
コントロールグループ

Dockerはまたgroupsまたはcontrol groupsと呼ばれる他の技術も使用します。隔離された中でアプリケーションを実行する鍵は、必要なリソースだけを使うようにそれらを持つことです。この守られたコンテナはホスト上で良い雑居状態の市民となります。コントロールグループはDockerにコンテナと有効なハードウェアリソースを共有することを許可し、もし必要なら制限と制約を設定します。例えば、特定のコンテナに対し、メモリの使用量を制限します。

Unionファイルシステム

UnionファイルシステムまたはUnionFSはレイヤーを生成するためのファイルシステムで、非常に軽量で、高速に生成します。コンテナのためのビルディングブロックを提供するためにDockerはunionファイルシステムを使います。Dockerは僅かに異なる幾つかのunionファイルシステム(AUFS,btrfs,vfs,そしてDeviceMapper)を使用できます。

コンテナフォーマット

Dockerは我々がコンテナフォーマットと呼ぶラッパー内にこれらのコンポーネントを結合します。デフォルトのコンテナフォーマットはlibcontainerと呼ばれます。Dockerはまた伝統的なLinuxコンテナとして使用されているLXCもサポートしています。Dockerは他のコンテナフォーマットもサポートするかもしれません。例えば、BSD JailsやSolaris Zonesなど。