ウェビナーシリーズ
この記事は、クラウドでのコンテナー化されたワークロードのデプロイと管理に関するウェビナーシリーズを補足するものです。 このシリーズでは、コンテナのライフサイクル管理、マルチコンテナアプリケーションのデプロイ、ワークロードのスケーリング、Kubernetesの理解など、コンテナの基本事項を取り上げ、ステートフルアプリケーションを実行するためのベストプラクティスを紹介します。
このチュートリアルには、シリーズの2番目のセッションであるコンテナ化されたアプリケーションの構築で説明されている概念とコマンドが含まれています。
序章
前回のチュートリアルDockerのインストールと構成方法では、DockerコンテナーをDockerイメージに変換する1つの方法について説明しました。 私たちが使用した方法は機能しましたが、それが常に画像を構築するための最適な方法であるとは限りません。
多くの場合、既存のコードをコンテナイメージに取り込み、コードベースの最新バージョンと同期するDockerイメージを作成するための反復可能で一貫性のあるメカニズムが必要になります。
Dockerfile は、Dockerイメージを構築するための宣言的で一貫した方法を提供することにより、これらの要件に対応します。
さらに、一緒にデプロイおよび管理される複数の異種コンテナーで構成されるアプリケーション全体をコンテナー化する必要がある場合があります。
Docker Compose は、Dockerfileと同様に、宣言型のアプローチを採用して、ネットワークとストレージの要件を含むテクノロジースタック全体を定義する方法を提供します。 これにより、コンテナ化されたアプリケーションの構築が容易になるだけでなく、それらの管理とスケーリングも容易になります。
このチュートリアルでは、Node.jsとMongoDBに基づくサンプルWebアプリケーションを使用してDockerfileからDockerイメージを構築し、Dockerコンテナーを許可するカスタムネットワークを作成します通信し、DockerComposeを使用してコンテナー化されたアプリケーションを起動およびスケーリングします。
前提条件
このチュートリアルに従うには、次のものが必要です。
- このUbuntu16.04初期サーバーセットアップチュートリアルに従ってセットアップされた1つのUbuntu16.04ドロップレット。これには、sudo非rootユーザーとファイアウォールが含まれます。
- このウェビナーシリーズの最初のチュートリアルに従ってインストールされたDockerCommunityEditionの最新バージョン。
ステップ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のブロックストレージおよびロードバランサーを利用して、コンテナー化されたアプリケーションに耐久性とスケーラビリティをもたらすことができます。