Dockerについて調べてみました

最近Dockerを触る機会があったので、理解するために調べたことを書いておきます。

*Dockerとは

Dockerを使って必要なライブラリなどがインストールした環境をコンテナイメージに固めておくことで、いつでも同一の開発環境を再現することができます。
プログラマが必要な環境を自分で用意できる、開発・テスト・サービス環境の差異を取り除くことができる、継続的デリバリ(CD:Continuous Delivery)の実現ができます。
これを自動化するには、Kubernetesなどのオーケストレーションツールが実現するコンテナインフラ環境と、マイクロサービスアーキテクチャの考え方が必要になります。
Dockerを導入するメリットとしては、コンテナの起動速度が早い、環境の変更の柔軟性があるといったことがありますが。本番検討ではよく検討する必要があります。
アプリのリリース後、V2.0の開発をする際にDockerは非常に役に立ちます。

*マイクロサービス

機能単位に分割して、それぞれを個別のコンテナで起動する手法のことです。該当部分のみ更新すればいいので変更の影響範囲を局所化して、事前に機能テストや問題発生時の切り戻しを容易にすることができます。

*Kubernetes

Kubernetesを使うことで同一機能のコンテナを複数起動してスケールアウトしたり、ブルー・グリーンデプロイ面とによって、サービスを停止せずに機能をアップデートすることが可能になります。
  • Kubernetesのしくみ
    DeploymentとServiceがあります。
    Deploymentは、ある特定の機能を提供するコンテナをどのような構成でデプロイするかを指定するしくみです。
    複数のノード(コンテナホスト)を束ねて1つのクラスタ=リソースプールとして管理します。
    Deploymentの設定ファイルを与えるとリソースの空いているノードを見つけて、自動的にコンテナのデプロイを行います。このとき、コンテナ数を指定することで、同一の機能を提供する複数のコンテナを起動することができます。何らかの障害でコンテナもしくはノードが停止した際は、自動的に再起動してくれます。
    複数のコンテナが起動するので、アクセスを振り分けるロードバランサの機能が必要になるのですが、それをServiceの設定ファイルで行います。
    DeploymentとServiceを組み合わせて実現するのが、ブルー・グリーンデプロイメントです。

*Dockerイメージ

Dockerでは1つのアプリを1つのコンテナに入れ、複数のコンテナを組み合わせてサービスを構築します。このコンテナのもとになるのがDockerイメージです。(イメージのなかに複数コンテナがあります)
Dockerイメージから複数のコンテナを起動することができます。
コンテナ内で動作するプロセスを1つのグループとして管理し、グループごとにそれぞれファイルシステムやホスト名、ネットワークなどを割り当てています。
Dockerイメージの実体は、アプリの実行に必要なファイル群が格納されたディレクトリツリーです。
DockerFile(テキストファイル)にDockerイメージの構成情報を記載して、これをもとにイメージをビルドすることができます。

*オーケストレーションツール

コンテナが正常動作しているか統合管理できるツールをコンテナオーケストレーションツールといいます。クラウド各社が提供しているコンテナ実行環境構築のフルマネージドサービスをうまく活用すると、手軽にコンテナの実行環境が容易できます。
(AWSではEC2、GCPではGCE)

*Google Container Engine(GKE)

GCPが提供するKubernetesのマネージドサービス環境です。フロントエンドとバックエンドを別々のコンテナで起動します。
  • メリット
    ・テスト済みの安全なアプリを本番環境に即座にデプロイ
    ・障害時での即時切り戻しが可能
    ・プログラマ自身でDocker実行環境の構築と運用を実現
    ・機能単位での短い開発サイクルによる継続的デリバリ
  • 流れ
    Dockerファイル --ビルド–> Google Container Registry
    Dockerイメージ --> GCEで実行環境にコンテナが作成
  • 使い方
    GKEを利用するためにまずプロジェクトを作成してアクセス権を設定します。また、API ManagerからGCE APIを有効にするボタンをクリックしてアクセス許可を行う必要があります。

*Dockerコマンド

Dockerfileからイメージを構築
docker build {パス}

コンテナのファイル変更内容をイメージ化
docker commit {コンテナ名 or リポジトリ:タグ}

イメージの構築履歴を表示
docker history {リポジトリ:タグ}

ローカルのイメージ一覧を表示
docker images {リポジトリ:タグ}

イメージの詳細情報を表示
docker inspect {リポジトリ:タグ}

Dockerレジストリからイメージやリポジトリをダウンロード
docker pull {リポジトリ:タグ}

イメージを削除
docker rmi {リポジトリ}

イメージをtarアーカイブとして保存(タグ付き)
docker save

イメージにタグを付与
docker tag {イメージ:タグ} {新しいリポジトリ:タグ}

新しいDockerコンテナを作成して起動 (pull、create、startを合わせたもの)
docker run {イメージ}

実行中のコンテナ一覧を表示 (停止中も表示する場合は-aオプションをつける)
docker ps

コンテナの標準出力を確認
docker logs {コンテナ}

流れ
リポジトリ
↓pull             commit
イメージ   イメージ      →イメージ
↓save   ↑import,load
tar     tar


*アプリケーションコンテナ

単一アプリケーションを動かすコンテナをアプリケーションコンテナのことです。docker runで起動します。
  • メリット
    永続化したデータをコンテナの外に置くことで、コンテナの起動終了でデータが失われません。複数台のサーバーを使うときはレジストリとサーバーを分けて配置するので向いています。
    メリットとしては、コンテナイメージが小さくなるため、デプロイにかかる時間が短くなるといったことがあげられます。
  • デメリット
    アプリケーションコンテナだけではサービスを動かすことができません。ストレージもコンテナ化してdocker-composeを利用する、クラウド上のマネージドサービスに開発マシンから直接接続することなどで、デメリットを軽減することができます。

*システムコンテナ

Webアプリの他にMySQLなど複数のアプリを動かすコンテナのことです。メリットは、コンテナイメージが1つあれば開発者でなくても誰でもすぐに動かすことができますし、コンテナを破棄するとデータも全て消えるので、ちょっとした動作確認に向いています。デメリットは、イメージが大きくなるといったことがあげられます。
本番環境はアプリケーションコンテナにするべきですが、
開発環境はライフサイクルによってアプローチが変わります。

*docker-compose

Dockerコンテナを複数起動するアプリケーションの構成をYAMLで定義し、まとめて起動するアプリケーションです。

*所感

Dockerを起動させると動くので、詳しい理解はできていなかったのですが、コンテナやイメージ、Dockerfileのことなど知ることで、どのような仕組みで動いているのかを理解することができました。うまく起動できずにエラーになったりする場合もあるので、根本的な調査ができるよう、Dockerfileを自分で書いたりして、より理解を深めておこうと思います。
Dockerコンテナをどの部分に導入するかはよく検討しなければいけないですが、積極的に導入してより速い開発をできるようにしていきたいです。