ウェビナーシリーズ

この記事は、クラウドでのコンテナー化されたワークロードのデプロイと管理に関するウェビナーシリーズを補足するものです。 このシリーズでは、コンテナーのライフサイクル管理、マルチコンテナーアプリケーションのデプロイ、ワークロードのスケーリング、Kubernetesの理解など、コンテナーの基本事項を取り上げ、ステートフルアプリケーションを実行するためのベストプラクティスを強調しています。

このチュートリアルには、シリーズの2番目のセッションであるコンテナ化されたアプリケーションの構築で説明されている概念とコマンドが含まれています。

序章

前回のチュートリアルDockerのインストールと構成方法では、DockerコンテナーDockerイメージに変換する1つの方法について説明しました。 私たちが使用した方法は機能しましたが、それが常に画像を構築するための最適な方法であるとは限りません。

多くの場合、既存のコードをコンテナイメージに取り込み、コードベースの最新バージョンと同期するDockerイメージを作成するための反復可能で一貫性のあるメカニズムが必要になります。

Dockerfile は、Dockerイメージを構築するための宣言的で一貫した方法を提供することにより、これらの要件に対応します。

さらに、一緒にデプロイおよび管理される複数の異種コンテナーで構成されるアプリケーション全体をコンテナー化する必要がある場合があります。

Docker Compose は、Dockerfileと同様に、宣言型のアプローチを採用して、ネットワークとストレージの要件を含むテクノロジースタック全体を定義する方法を提供します。 これにより、コンテナ化されたアプリケーションの構築が容易になるだけでなく、それらの管理とスケーリングも容易になります。

このチュートリアルでは、Node.jsMongoDBに基づくサンプルWebアプリケーションを使用してDockerfileからDockerイメージを構築し、Dockerコンテナーを許可するカスタムネットワークを作成します通信し、DockerComposeを使用してコンテナー化されたアプリケーションを起動およびスケーリングします。

前提条件

このチュートリアルに従うには、次のものが必要です。

ステップ1—Dockerfileを使用してイメージを構築する

まずホームディレクトリに移動し、 Git を使用して、GitHub公式リポジトリからこのチュートリアルのサンプルWebアプリケーションのクローンを作成します。

  1. cd ~
  2. git clone https://github.com/janakiramm/todo-app.git

これにより、サンプルアプリケーションがtodo-appという名前の新しいディレクトリにコピーされます。

todo-appに切り替え、lsを使用してディレクトリの内容を表示します。

  1. cd todo-app
  2. ls

新しいディレクトリには、2つのサブディレクトリと2つのファイルが含まれています。

  • app-サンプルアプリケーションのソースコードが保存されているディレクトリ
  • compose-DockerCompose構成ファイルが保存されているディレクトリ
  • Dockerfile-Dockerイメージをビルドするための手順を含むファイル
  • README.md-サンプルアプリケーションの1文の要約を含むファイル

cat Dockerfileを実行すると、次のように表示されます。

〜/ todo-app / Dockerfile
FROM node:slim
LABEL maintainer = "[email protected]"
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY ./app/ ./
RUN npm install
CMD ["node", "app.js"]

このファイルの内容をさらに詳しく見てみましょう。

  • FROMは、カスタムイメージを構築するベースイメージを示します。 この例では、イメージはnode:slimに基づいています。これは、nodeの実行に必要な最小限のパッケージのみを含むpublicNode.jsイメージです。
  • LABELは、説明情報を追加するために通常使用されるキーと値のペアです。 この場合、メンテナのメールアドレスが含まれています。
  • RUNはコンテナ内でコマンドを実行します。 これには、ディレクトリの作成や、基本的なLinuxコマンドの実行によるコンテナの初期化などのタスクが含まれます。 このファイルの最初のRUNコマンドは、ソースコードを保持するディレクトリ/usr/src/appを作成するために使用されます。
  • WORKDIRは、すべてのコマンドが実行されるディレクトリを定義します。 これは通常、コードがコピーされるディレクトリです。
  • COPYは、ファイルをホストマシンからコンテナイメージにコピーします。 この場合、appディレクトリ全体をイメージにコピーしています。
  • 2番目のRUNコマンドは、npm installを実行して、package.jsonで定義されているアプリケーションの依存関係をインストールします。
  • CMDは、コンテナの実行を維持するプロセスを実行します。 この例では、パラメーターapp.jsを指定してnodeを実行します。

次に、Dockerfileからイメージを作成します。 -tスイッチを使用して、レジストリのユーザー名、イメージ名、およびオプションのタグでイメージにタグを付けます。

  1. docker build -t sammy/todo-web .

出力は、画像がSuccessfully builtであり、適切にタグ付けされていることを確認します。

Output from docker build -t
Sending build context to Docker daemon 8.238MB Step 1/7 : FROM node:slim ---> 286b1e0e7d3f Step 2/7 : LABEL maintainer = "[email protected]" ---> Using cache ---> ab0e049cf6f8 Step 3/7 : RUN mkdir -p /usr/src/app ---> Using cache ---> 897176832f4d Step 4/7 : WORKDIR /usr/src/app ---> Using cache ---> 3670f0147bed Step 5/7 : COPY ./app/ ./ ---> Using cache ---> e28c7c1be1a0 Step 6/7 : RUN npm install ---> Using cache ---> 7ce5b1d0aa65 Step 7/7 : CMD node app.js ---> Using cache ---> 2cef2238de24 Successfully built 2cef2238de24 Successfully tagged sammy/todo-web:latest

docker imagesコマンドを実行すると、イメージが作成されたことを確認できます。

  1. docker images

ここでは、画像のサイズと、画像が作成されてからの経過時間を確認できます。

Output from docker images
REPOSITORY TAG IMAGE ID CREATED SIZE sammy/todo-web latest 81f5f605d1ca 9 minutes ago 236MB

サンプルWebアプリケーションを実行するためのMongoDBコンテナーも必要なので、それをマシンに取得しましょう。

  1. docker pull mongo:latest

出力は、ダウンロードステータスとともにどのイメージがプルされたかを正確に報告します。

Output from docker pull
latest: Pulling from library/mongo Digest: sha256:18b239b996e0d10f4ce2b0f64db6f410c17ad337e2cecb6210a3dcf2f732ed82 Status: Downloaded newer image for mongo:latest

これで、サンプルアプリケーションを実行するために必要なものがすべて揃ったので、コンテナが相互に通信できるようにするカスタムネットワークを作成しましょう。

docker runコマンドを使用してWebアプリケーションとデータベースコンテナを個別に起動すると、それらはお互いを見つけることができなくなります。

理由を確認するには、Webアプリケーションのデータベース構成ファイルの内容を表示してください。

  1. cat app/db.js

Mongoose (Node.jsのMongoDBオブジェクトモデリングライブラリ)をインポートし、新しいデータベーススキーマを定義した後、Webアプリケーションはホスト名db、まだ存在していません。

〜/ todo-app / app / db.js
var mongoose = require( 'mongoose' );
var Schema   = mongoose.Schema;

var Todo = new Schema({
    user_id    : String,
    content    : String,
    updated_at : Date
});

mongoose.model( 'Todo', Todo );

mongoose.connect( 'mongodb://db/express-todo' );

同じアプリケーションに属するコンテナがお互いを確実に検出できるようにするには、同じネットワーク上でそれらを起動する必要があります。

Dockerは、インストール中に作成されたデフォルトネットワークに加えて、カスタムネットワークを作成する機能を提供します。

次のコマンドを使用して、現在利用可能なネットワークを確認できます。

  1. docker network ls

Dockerによって作成された各ネットワークは、ドライバーに基づいています。 次の出力では、bridgeという名前のネットワークがドライバーbridgeに基づいていることがわかります。 localスコープは、ネットワークがこのホストでのみ使用可能であることを示します。

Output from docker network ls
NETWORK ID NAME DRIVER SCOPE 5029df19d0cf bridge bridge local 367330960d5c host host local f280c1593b89 none null local

次に、アプリケーション用にtodo_netという名前のカスタムネットワークを作成し、そのネットワーク上でコンテナーを起動します。

  1. docker network create todo_net

出力は、作成されたネットワークのハッシュを示します。

Output from docker network create
C09f199809ccb9928dd9a93408612bb99ae08bb5a65833fefd6db2181bfe17ac

ここで、使用可能なネットワークを再度リストします。

  1. docker network ls

ここで、todo_netを使用する準備ができていることがわかります。

Output from docker network ls
NETWORK ID NAME DRIVER SCOPE c51377a045ff bridge bridge local 2e4106b07544 host host local 7a8b4801a712 none null local bc992f0b2be6 todo_net bridge local

docker runコマンドを使用すると、--networkスイッチでこのネットワークを参照できるようになります。 特定のホスト名でWebコンテナとデータベースコンテナの両方を起動してみましょう。 これにより、コンテナがこれらのホスト名を介して相互に接続できるようになります。

まず、MongoDBデータベースコンテナを起動します。

  1. docker run -d \
  2. --name=db \
  3. --hostname=db \
  4. --network=todo_net \
  5. mongo

そのコマンドを詳しく見ると、次のことがわかります。

  • -dスイッチは、コンテナをデタッチモードで実行します。
  • --nameおよび--hostnameスイッチは、ユーザー定義の名前をコンテナーに割り当てます。 --hostnameスイッチは、Dockerによって管理されるDNSサービスにもエントリを追加します。 これは、ホスト名でコンテナを解決するのに役立ちます。
  • --networkスイッチは、デフォルトのブリッジネットワークではなく、カスタムネットワークでコンテナーを起動するようにDockerEngineに指示します。

docker runコマンドからの出力として長い文字列が表示された場合、コンテナーは正常に起動されたと見なすことができます。 ただし、これはコンテナが実際に実行されていることを保証するものではありません。

Output docker run
aa56250f2421c5112cf8e383b68faefea91cd4b6da846cbc56cf3a0f04ff4295

dbコンテナが起動し、docker logsコマンドで実行されていることを確認します。

  1. docker logs db

これにより、コンテナログがstdoutに出力されます。 ログの最後の行は、MongoDBの準備ができており、waiting for connectionsであることを示しています。

Output from docker logs
2017-12-10T02:55:08.284+0000 I CONTROL [initandlisten] MongoDB starting : pid=1 port=27017 dbpath=/data/db 64-bit host=db . . . . 2017-12-10T02:55:08.366+0000 I NETWORK [initandlisten] waiting for connections on port 27017

それでは、Webコンテナを起動して確認しましょう。 今回は、ホストのポート3000をコンテナーのポート3000に公開する--publish=3000:3000も含まれています。

  1. docker run -d \
  2. --name=web \
  3. --publish=3000:3000 \
  4. --hostname=web \
  5. --network=todo_net \
  6. sammy/todo-web

以前と同様に、出力として長い文字列を受け取ります。

また、このコンテナが稼働していることを確認しましょう。

  1. docker logs web

出力は、 Express (テストアプリケーションのベースとなっているNode.jsフレームワーク)がlistening on port 3000であることを確認します。

Output from docker logs
Express server listening on port 3000

pingコマンドを使用して、Webコンテナーがdbコンテナーと通信できることを確認します。 これを行うには、疑似TTY(-t)に接続されたインタラクティブ(-i)モードでdocker execコマンドを実行します。

  1. docker exec -it web ping db

このコマンドは、標準のping出力を生成し、2つのコンテナーが相互に通信できることを通知します。

Output from docker exec -it web ping db
PING db (172.18.0.2): 56 data bytes 64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.210 ms 64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.095 ms ...

CTRL+Cを押して、pingコマンドを停止します。

最後に、Webブラウザでhttp://your_server_ip:3000を指定して、サンプルアプリケーションにアクセスします。 Containers Todo Example というラベルの付いたWebページと、Todoタスクを入力として受け入れるテキストボックスが表示されます。

名前の競合を回避するために、docker rmおよびdocker network removeコマンドを使用して、コンテナーを停止し、リソースをクリーンアップできるようになりました。

  1. docker rm -f db
  2. docker rm -f web
  3. docker network remove todo_net

この時点で、2つの別々のコンテナーで構成されるコンテナー化されたWebアプリケーションができました。 次のステップでは、より堅牢なアプローチを検討します。

ステップ3—マルチコンテナアプリケーションのデプロイ

リンクされたコンテナーを起動することはできましたが、マルチコンテナーアプリケーションを処理するための最も洗練された方法ではありません。 関連するすべてのコンテナを宣言し、それらを1つの論理ユニットとして管理するためのより良い方法が必要です。

Docker Composeは、開発者がマルチコンテナーアプリケーションを処理するために利用できるフレームワークです。 Dockefileと同様に、スタック全体を定義するための宣言型メカニズムです。 次に、Node.jsおよびMongoDBアプリケーションをDockerComposeベースのアプリケーションに変換します。

DockerComposeをインストールすることから始めます。

  1. sudo apt-get install -y docker-compose

サンプルWebアプリケーションのcomposeディレクトリにあるdocker-compose.yamlファイルを調べてみましょう。

  1. cat compose/docker-compose.yaml

docker-compose.yamlファイルはすべてをまとめます。 これは、MongoDBコンテナーをdb:ブロックに、Node.js Webコンテナーをweb:ブロックに、カスタムネットワークをnetworks:ブロックに定義します。

build: ../.ディレクティブでは、ComposeがappディレクトリのDockerfileを指していることに注意してください。 これにより、Webコンテナを起動する前にイメージをビルドするようにComposeに指示します。

〜/ todo-app / compose / docker-compose.yaml
version: '2'
services:
  db:
    image: mongo:latest
    container_name: db
    networks:
      - todonet
  web:
    build: ../.
    networks:
      - todonet
    ports:
     - "3000"
networks:
  todonet:
    driver: bridge

次に、composeディレクトリに移動し、docker-compose upコマンドを使用してアプリケーションを起動します。 docker runと同様に、-dスイッチはコンテナをデタッチモードで起動します。

  1. cd compose
  2. docker-compose up -d

出力は、DockerComposeがcompose_todonetというネットワークを作成し、その上で両方のコンテナーを起動したことを報告します。

Output from docker-compose up -d
Creating network "compose_todonet" with driver "bridge" Creating db Creating compose_web_1

明示的なホストポートマッピングを提供していないことに注意してください。 これにより、Docker Composeはランダムなポートを割り当てて、ホスト上のWebアプリケーションを公開します。 次のコマンドを実行すると、そのポートを見つけることができます。

  1. docker ps

Webアプリケーションがホストポート32782で公開されていることがわかります。

Output from docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6700761c0a1e compose_web "node app.js" 2 minutes ago Up 2 minutes 0.0.0.0:32782->3000/tcp compose_web_1 ad7656ef5db7 mongo:latest "docker-entrypoint..." 2 minutes ago Up 2 minutes 27017/tcp db

Webブラウザをhttp://your_server_ip:32782に移動して、これを確認します。 これにより、ステップ2の最後に表示されたとおりにWebアプリケーションが表示されます。

マルチコンテナーアプリケーションがDockerComposeを介して稼働している状態で、アプリケーションの管理とスケーリングを見てみましょう。

ステップ4—アプリケーションの管理とスケーリング

Docker Composeを使用すると、ステートレスWebアプリケーションを簡単にスケーリングできます。 1つのコマンドでwebコンテナの10個のインスタンスを起動できます。

  1. docker-compose scale web=10

出力により、インスタンスが作成および開始されているのをリアルタイムで監視できます。

Output from docker-compose scale
Creating and starting compose_web_2 ... done Creating and starting compose_web_3 ... done Creating and starting compose_web_4 ... done Creating and starting compose_web_5 ... done Creating and starting compose_web_6 ... done Creating and starting compose_web_7 ... done Creating and starting compose_web_8 ... done Creating and starting compose_web_9 ... done Creating and starting compose_web_10 ... done

docker psを実行して、Webアプリケーションが10インスタンスにスケーリングされていることを確認します。

  1. docker ps

Dockerが、ホスト上の各webコンテナーを公開するためにランダムなポートを割り当てていることに注意してください。 これらのポートのいずれかを使用して、アプリケーションにアクセスできます。

Output from docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cec405db568d compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32788->3000/tcp compose_web_9 56adb12640bb compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32791->3000/tcp compose_web_10 4a1005d1356a compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32790->3000/tcp compose_web_7 869077de9cb1 compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32785->3000/tcp compose_web_8 eef86c56d16f compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32783->3000/tcp compose_web_4 26dbce7f6dab compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32786->3000/tcp compose_web_5 0b3abd8eee84 compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32784->3000/tcp compose_web_3 8f867f60d11d compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32789->3000/tcp compose_web_6 36b817c6110b compose_web "node app.js" About a minute ago Up About a minute 0.0.0.0:32787->3000/tcp compose_web_2 6700761c0a1e compose_web "node app.js" 7 minutes ago Up 7 minutes 0.0.0.0:32782->3000/tcp compose_web_1 ad7656ef5db7 mongo:latest "docker-entrypoint..." 7 minutes ago Up 7 minutes 27017/tcp db

同じコマンドでWebコンテナをスケールインすることもできます。

  1. docker-compose scale web=2

今回は、余分なインスタンスがリアルタイムで削除されているのがわかります。

Output from docker-compose
Stopping and removing compose_web_3 ... done Stopping and removing compose_web_4 ... done Stopping and removing compose_web_5 ... done Stopping and removing compose_web_6 ... done Stopping and removing compose_web_7 ... done Stopping and removing compose_web_8 ... done Stopping and removing compose_web_9 ... done Stopping and removing compose_web_10 ... done

最後に、インスタンスを再確認します。

  1. docker ps

出力は、インスタンスが2つだけ残っていることを確認します。

Output from docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 36b817c6110b compose_web "node app.js" 3 minutes ago Up 3 minutes 0.0.0.0:32787->3000/tcp compose_web_2 6700761c0a1e compose_web "node app.js" 9 minutes ago Up 9 minutes 0.0.0.0:32782->3000/tcp compose_web_1 ad7656ef5db7 mongo:latest "docker-entrypoint..." 9 minutes ago Up 9 minutes 27017/tcp db

これで、アプリケーションを停止できます。また、以前と同様に、リソースをクリーンアップして、名前の競合を回避することもできます。

  1. docker-compose stop
  2. docker-compose rm -f
  3. docker network remove compose_todonet

結論

このチュートリアルでは、DockerfilesとDockerComposeを紹介しました。 イメージを構築するための宣言型メカニズムとしてDockerfileから始め、次にDockerネットワークの基本を探りました。 最後に、DockerComposeを使用してマルチコンテナーアプリケーションをスケーリングおよび管理しました。

新しいセットアップを拡張するには、別のコンテナー内で実行されている Nginxリバースプロキシを追加して、使用可能なWebアプリケーションコンテナーの1つにリクエストをルーティングします。 または、DigitalOceanのブロックストレージおよびロードバランサーを利用して、コンテナー化されたアプリケーションに耐久性とスケーラビリティをもたらすことができます。