ウェビナーシリーズ:コンテナ化されたアプリケーションの構築

提供:Dev Guides
移動先:案内検索

ウェビナーシリーズ

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

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


YouTubeビデオを見る

序章

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

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

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

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

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

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

前提条件

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

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

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

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

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

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

cd todo-app
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スイッチを使用して、レジストリのユーザー名、イメージ名、およびオプションのタグでイメージにタグを付けます。

docker build -t sammy/todo-web .

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

Output from docker build -tSending 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コマンドを実行すると、イメージが作成されたことを確認できます。

docker images

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

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

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

docker pull mongo:latest

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

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

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

ステップ2—コンテナをリンクするネットワークを作成する

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

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

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

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

docker network ls

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

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

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

docker network create todo_net

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

Output from docker network createC09f199809ccb9928dd9a93408612bb99ae08bb5a65833fefd6db2181bfe17ac

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

docker network ls

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

Output from docker network lsNETWORK 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データベースコンテナを起動します。

docker run -d \
--name=db \
--hostname=db \
--network=todo_net \
mongo

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

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

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

Output docker runaa56250f2421c5112cf8e383b68faefea91cd4b6da846cbc56cf3a0f04ff4295

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

docker logs db

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

Output from docker logs2017-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も含まれています。

docker run -d \
--name=web \
--publish=3000:3000 \
--hostname=web \
--network=todo_net \
sammy/todo-web

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

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

docker logs web

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

Output from docker logsExpress server listening on port 3000

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

docker exec -it web ping db

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

Output from docker exec -it web ping dbPING 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コマンドを使用して、コンテナーを停止し、リソースをクリーンアップできるようになりました。

docker rm -f db
docker rm -f web
docker network remove todo_net

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

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

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

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

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

sudo apt-get install -y docker-compose 

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

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スイッチはコンテナをデタッチモードで起動します。

cd compose
docker-compose up -d

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

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

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

docker ps

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

Output from docker psCONTAINER 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個のインスタンスを起動できます。

docker-compose scale web=10

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

Output from docker-compose scaleCreating 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インスタンスにスケーリングされていることを確認します。

docker ps

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

Output from docker psCONTAINER 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コンテナをスケールインすることもできます。

docker-compose scale web=2

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

Output from docker-composeStopping 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

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

docker ps

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

Output from docker psCONTAINER 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

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

docker-compose stop
docker-compose rm -f
docker network remove compose_todonet

結論

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

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