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

前書き

最後のチュートリアルhttps://www.digitalocean.com/community/tutorials/how-to-install-and-configure-docker[Dockerのインストールおよび構成方法]では、https:// wwwを変換する1つの方法を検討しました。 .digitalocean.com / community / tutorials / how-to-install-and-configure-docker#step-2-%E2%80%94-launching-containers [Docker container] into https://www.digitalocean.com/ community / tutorials / how-to-install-and-configure-docker#step-4-%E2%80%94-building-images [Docker images]。 使用した方法は機能しましたが、画像を構築する最適な方法とは限りません。

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

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

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

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

このチュートリアルでは、https://nodejs.org/ [Node.js]およびhttps://www.mongodb.com/[MongoDB]に基づいたサンプルWebアプリケーションを使用して、DockerfileからDockerイメージを構築します。 Dockerコンテナが通信できるカスタムネットワークを作成し、Docker Composeを使用してコンテナ化されたアプリケーションを起動およびスケーリングします。

前提条件

このチュートリアルを実行するには、次のものが必要です。

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

まずホームディレクトリに移動し、https://git-scm.com/ [Git]を使用して、このチュートリアルのサンプルWebアプリケーションをhttps://github.com/janakiramm/todo-app.git [公式リポジトリ]から複製しますGitHub]。

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

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

`+ todo-app `に切り替え、 ` ls +`を使用してディレクトリのコンテンツを表示します。

cd todo-app
ls

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

  • + app +-サンプルアプリケーションのソースコードが保存されているディレクトリ

  • + compose +-Docker Compose構成ファイルが保存されているディレクトリ

  • + 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 `に基づいています。これは、https://hub.docker.com/_/node/ [public Node.js image]であり、 ` node + `。

  • 「+ 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 /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
2cef2238de24
/todo-web:latest

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

docker images

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

Output from docker imagesREPOSITORY                                       TAG                 IMAGE ID            CREATED             SIZE
/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

Node.js用のMongoDBオブジェクトモデリングライブラリであるhttp://mongoosejs.com/[Mongoose]をインポートし、新しいhttps://www.digitalocean.com/community/tutorials/understanding-sql-and-nosqlを定義した後-databases-and-different-database-models [database schema]、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:///express-todo' );

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

Dockerは、インストール中に作成されたhttps://docs.docker.com/engine/userguide/networking/ [デフォルトネットワーク]に加えて、カスタムネットワークを作成する機能を提供します。

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

docker network ls

Dockerによって作成された各ネットワークは、https://blog.docker.com/2016/12/understanding-docker-networking-drivers-use-cases/ [driver]に基づいています。 次の出力では、「+ bridge 」という名前のネットワークがドライバー「 bridge 」に基づいていることがわかります。 ` local +`スコープは、ネットワークがこのホストでのみ利用可能であることを示します。

Output from docker network lsNETWORK ID          NAME                DRIVER              SCOPE
5029df19d0cf
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

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

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

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

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

  • `+ -d +`スイッチはhttps://docs.docker.com/engine/reference/run/#detached—​d[detached mode]でコンテナを実行します。

  • `-name +`および `-hostname `スイッチは、コンテナにユーザー定義の名前を割り当てます。 `-hostname +`スイッチは、https://docs.docker.com/engine/userguide/networking/configure-dns/ [Dockerによって管理されるDNSサービス]にもエントリを追加します。 これは、ホスト名でコンテナを解決するのに役立ちます。

  • `+-network +`スイッチは、デフォルトのブリッジネットワークではなくカスタムネットワークでコンテナを起動するようにDocker Engineに指示します。

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

Output docker runaa56250f2421c5112cf8e383b68faefea91cd4b6da846cbc56cf3a0f04ff4295

`+ docker logs `コマンドを使用して、 ` db +`コンテナが稼働していることを確認します。

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]  on port 27017

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

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

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

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

docker logs web

出力は、https://expressjs.com/ [Express](テストアプリケーションのベースとなるNode.jsフレームワーク)が「+ポート3000+でリッスンしている」ことを確認します。

Output from docker logsExpress server listening on port 3000

Webコンテナが「+ ping 」コマンドを使用して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
...

`+ ping `コマンドを停止するには、 ` CTRL + C +`を押します。

最後に、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アプリケーションをDocker Composeベースのアプリケーションに変換します。

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

sudo apt-get install -y docker-compose

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

cat compose/docker-compose.yaml

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

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

〜/ todo-app / compose / docker-compose.yml

version: '2'
services:
 db:
   image: mongo:latest
   container_name: db
   networks:
     - todonet
 web:
   build: ../.
   networks:
     - todonet
   ports:
    - "3000"
networks:
 todonet:
   driver: bridge

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

cd compose
docker-compose up -d

出力は、Docker Composeが `+ 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:->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 +`に移動します。 これにより、リンクの最後で見たとおりにWebアプリケーションが表示されます:#step-2-%E2%80%94-creating-a-network-to-link-containers [ステップ2]。

Docker Composeを使用してマルチコンテナアプリケーションを起動および実行したら、アプリケーションの管理とスケーリングを見てみましょう。

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

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

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:->3000/tcp   compose_web_9
56adb12640bb        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_10
4a1005d1356a        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_7
869077de9cb1        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_8
eef86c56d16f        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_4
26dbce7f6dab        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_5
0b3abd8eee84        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_3
8f867f60d11d        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_6
36b817c6110b        compose_web         "node app.js"            About a minute ago   Up About a minute   0.0.0.0:->3000/tcp   compose_web_2
6700761c0a1e        compose_web         "node app.js"            7 minutes ago        Up 7 minutes        0.0.0.0:->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およびDocker Composeを紹介しました。 イメージを構築するための宣言メカニズムとしてDockerfileから始め、次にDockerネットワーキングの基本を調べました。 最後に、Docker Composeを使用してマルチコンテナアプリケーションをスケーリングおよび管理しました。

新しいセットアップを拡張するには、別のコンテナ内で実行されているhttps://www.digitalocean.com/community/tutorials/understanding-nginx-http-proxying-load-balancing-buffering-and-caching[Nginx reverse proxy]を追加します。利用可能なWebアプリケーションコンテナの1つにリクエストをルーティングします。 または、https://www.digitalocean.com/community/tutorials/how-to-use-block-storage-on-digitalocean [DigitalOcean’s Block Storage]およびhttps://www.digitalocean.com/を利用できます。 community / tutorials / an-introduction-to-digitalocean-load-balancers [Load Balancers]は、コンテナ化されたアプリケーションに耐久性とスケーラビリティをもたらします。

前の投稿:CDNを使用して静的コンテンツ配信を高速化する
次の投稿:Ubuntu 14.04でNginxとPhp-fpmを使用して複数のWebサイトを安全にホストする方法