前書き
最後のチュートリアル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を使用してコンテナ化されたアプリケーションを起動およびスケーリングします。
前提条件
このチュートリアルを実行するには、次のものが必要です。
-
このhttps://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04[Ubuntu 16.04初期サーバーセットアップチュートリアル]に従って、1つのUbuntu 16.04ドロップレットをセットアップしました。 rootユーザーとファイアウォール。
-
https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-docker#step-4-%E2%80%94-building-imagesに従ってインストールされたDocker Community Editionの最新バージョン[このウェビナーシリーズの最初のチュートリアル]。
ステップ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]は、コンテナ化されたアプリケーションに耐久性とスケーラビリティをもたらします。