DockerでMEAN Stackの稼働環境を簡単実現
by Shuichi Ohtsu
ビデオ解説(日本語)
https://youtu.be/RJsJ6jcJDGM
ビデオ解説(英語)
https://youtu.be/mjKe-FF4gMc
Full Source Code
https://github.com/Ohtsu/mean_stack_on_docker
動作環境
今回は、WSL上のDockerを利用することにより、MEAN Stackの環境を簡単に作成する例をご紹介いたします。
MEAN Stackとは、世界中に普及している、JavaScriptベースのフリーソフトの頭文字をとって名付けたものです。
Mは、データベースのMongoDB、Eは、Webサーバを簡単に構築できるミドルウェアのExpress、AはGoogle社がフリーで提供しているクライアント用フレームワークであるAngularを表しており、NはJavaScriptをベースとして、クライアント及びサーバの共通基盤を提供するNode.jsを表しています。
最も重要な点は、JavaScriptでサーバからクライアントまでの環境を構築できる点です。
すなわち、どのようなデバイスであろうと、ブラウザが内装されているのであれば、稼働できてしまいます。
従来開発者を悩ましていた、稼働環境の違いをすべてクリアしてしまうのです。
Windows環境であろうと、Linux環境であろうと、あるいはMac環境であろうと、問題なく稼働できてしまいます。しかも、サーバ環境も含めてです。
さらに受け手であるデバイス環境も問いません。すなわち、デスクトップ・マシンであろうが、スマートフォンであろうが、問題なく稼働します。
この表示については、特にAngular Materialを利用することにより、デバイス環境を意識しないで済むことになります。
今回は、Angular7ベースのAngular Materialを利用することにより、この機能を実現しています。
デスクトップ表示
スマートフォン表示
docker-composeのインストール
まず、WSL上のUbuntuを開きます。
そして、sudo apt update
と入力して、更新情報を取得します。
次に、sudo apt upgrade
と入力して、この更新情報に基づいて、アップグレードを行います。
次に、目的の _docker-compose_をインストールします。
sudo apt install docker-compose
と入力します。
クライアント、Rest API、サーバソフトのインストール
次に今回利用する、クライアント、ミドルウェア並びにサーバソフトのソースをダウンロードします。
ブラウザで、GitHubのサイトを開きます。
そのURLは、https://github.com/Ohtsu/mean_stack_on_dockerです。
ページが表示されましたら、右側の _Clone or download_をクリックし、そのダウンロード・アドレスをコピーします。
まず、ダウンロード用のディレクトリを作成します。
ここでは、/mnt/c/__myprg
内に __dummy
ディレクトリを作成しました。
そして、このディレクトリ内で、
git clone https://gitgub.com/Ohtsu/mean_stack_on_docker.git
と入力して、ソースをダウンロードします。
次に、このディレクトリ内で、code .
と入力して、Visual Studio Codeを起動します。
docker-composeファイルの確認
まず、docker-composeファイルの内容を確認します。
このファイルでは、クライアント、サーバソフトなどの連携関係を記述しています。
たとえば、クライアント・ソフトであるAngular関連のソフトは、MongoDBに依存しています。
version: "3.3"
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "8080:80"
networks:
- webnet
depends_on:
- mongo
- backend
links:
- backend
mongo:
image: mongo
restart: always
volumes:
- mongodb-data:/data/db
environment:
MONGO_INITDB_ROOT_USERNAME: username
MONGO_INITDB_ROOT_PASSWORD: password
ports:
- 27017:27017
networks:
- webnet
mongo-express:
container_name: mongo-express
image: mongo-express
restart: always
ports:
- 8081:8081
networks:
- webnet
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: username
ME_CONFIG_MONGODB_ADMINPASSWORD: password
ME_CONFIG_BASICAUTH_UERNAME: username
ME_CONFIG_BASICAUTH_PASSWORD: password
depends_on:
- mongo
links:
- mongo
backend:
build:
context: ./backend
dockerfile: Dockerfile
restart: always
ports:
- "5000:5000"
networks:
- webnet
depends_on:
- mongo
links:
- mongo
networks:
webnet:
volumes:
mongodb-data:
また、ミドルウェアである、Express関連のソフトもMongoDBに依存しています。
これらは、depends_on
及びlinks
のコマンドで指定しています・
また、MongoDB関連では、初期設定用の管理者ユーザ名及びそのパスワードも指定しています。
これらのユーザ名やパスワードは、次にご紹介する、MongoDB管理ツールで使用しますので、銘記しておいください。
Dockerfileファイルの確認
まず、Express関連のDockerfileについてですが、カレントディレクトリにあるファイル群をコンテナ内にコピーし、npm install
を実行しています。
# stage 1
FROM node:alpine as node
WORKDIR /app
COPY . .
RUN npm install
# RUN npm run build
EXPOSE 5000
ENTRYPOINT [ "node", "server.js" ]
また、ポート番号5000を公開しています。
次に、クライアント関連のAngularファイルについてですが、まずDockerfileを開いてみます。
# stage 1
FROM node:10.12 as node
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build --prod
# # stage 2
FROM nginx:alpine
COPY --from=node /app/dist/frontend /usr/share/nginx/html
このファイルの指定は2段階になっています。
すなわち、まず同一の環境をコンテナ内に構築し、プロダクションモードでコンパイルします。
その生成されたJavaScript圧縮ファイルを、軽量のAlpineLinux上のnginxのホームにコピーします。
なお、このクライアントソフトは、Markdownの編集ソフトという形になっていますので、MarkdownからHTMLへの変換ツールであるmarkdown-it
もインストールしていることに注意してください。
まず、docker-compose up
と入力し、関連のDockerイメージを作成します。
次に、docker-compose down
と入力し、一旦すべての関連コンテナを削除します。
まず、クライアントでの表示用に、MongoDBにデータを登録する必要があります。
これは、コンテナ・イメージを先に生成するための手続きです。
というのは、docker-compose
において各ソフトウェアの起動順序をdepends_on
などによって、指定してもMongoDBなどのデータベースの起動に時間がかかる場合は、イメージを作成中に連携エラーとなってしまうからです。
MongoDBデータの入力
次に、MongoDBにサンプルデータを入力することにします。
まず、一旦、docker-compose down
と入力して、すべてのコンテナを削除し、再度docker-compose up mongo
と入力し、MongoDBだけを起動します。
ここでは、MongoDBデータの入力用に、_Studio 3T_というツールを利用しています。
試用期間中はフリーですのでMongoDBユーザにとっては大変便利なツールです。
まず、MongoDBに接続する必要があります。
_Studio 3T_を起動後、コネクション・アイコンをクリックします。
そして新規コネクションを選択し、サーバ名を適当に入力した後、Authentications
タブを選択します。
そしてさらに、Authentication Mode
においてBasic
を選択し、docker-compose
ファイルで管理者用に設定している、ユーザ名(username)とパスワード(password)をここにも同様に設定します。
そして、左下のTest Connection
ボタンをクリックして、OK
であれば、接続完了です。
Save
ボタンをクリックし、この設定を保存します。
さらに、Connect
ボタンをクリックし、接続します。
次に、IntelliShell
ボタンをクリックし、MongoDBシェルウィンドウを開き、use blog
と入力し、blogデータベースを作成します。
再度、IntelliShell
ボタンをクリックし、データを登録します。これはGitHubに登録してありますので、そのファイルを貼り付けて登録します。
最後に、参照ユーザ(sample)のアクセス権限を登録します。
これもGitHubに登録してあるものをそのまま利用します。
サーバ及びクライアントソフトの起動
まず、起動中のMongoDBを停止します。
docker-compose down
と入力します。
次に、すべてのソフトウェアを起動します。
docker-compose up
と入力します。
クライアントソフトの確認
データベース、Express並びにAngularがうまく連携していれば、http:localhost:8080
にブラウザ上でアクセスすれば、スマホにも対応した_Markdown Editor_が起動できます。
このソフトは、Angular Materialの機能を利用しており、デスクトップマシンやスマートフォンなどの画面解像度に応じて、スタイルが設定されているようになっています。
また、ページング機能、各列ごとのソート機能なども有効になっています。
表示行数も変更可能です。
各列のヘッダの矢印をクリックすると、その列をキーとしてソートが行われます。
右下のアイコンをクリックすると、次ページが表示されます。
各列のEdit
ボタンをクリックすると、修正用のページが表示されます。
各列のView
ボタンをクリックすると、Markdownが認識されたページが表示されます。
デスクトップ表示
スマートフォン表示
最後に
このシステムの作成については、簡単にできると考えていましたが、意外に時間がかかってしまいました。
その原因は、Docker-Composeファイルにおけるdepends_on
やlinks
の使い方がよくわかっていなかったからによります。Web上の情報では、links
はいずれ廃止されるとのことであり、また他の実装例でもlinks
は記述されていなかったので(たぶんRedisをベースとしていたことが影響していると思います)、当初から使用していませんでした。
ところが何度繰り返してもうまく稼働しません。そうこうしているうちに、下記参考文献の"Cannot connect to MongoDB via node.js in Docker"のページに出会い、試しにlinks
を使用してみました。
すると簡単にMongoDBに接続することができました。これには、各コンテナ間の連携に、接続のタイミングが影響していることが伺えます。
幸い、下記参考文献上の『プログラマのためのDocker教科書 第2版 インフラの基礎知識&コードによる環境構築の自動化』の231ページにある「ここで注意していただきたいのは、depends_onがコンテナの開始の順序を制御するだけで、コンテナ上のアプリケーションが利用可能になるまで待つという制御を行わない点です。つまり、依存関係にあるデータベースサーバの準備が整うまで待つわけではないため、アプリケーション側で対策する必要があります。」との記述をかすかに覚えていました。
そこで、時間のかかるDockerイメージの作成を行い、そして一旦Docker-Composeを中断し、再起動するという方法をとることにしました。
これにより、ローカル上の既存のDockerイメージを利用できるので、各コンテナの接続がうまくいくことになりました。
皆さんもぜひこの点に注意してください。
Reference
MEAN Stack
-
"Angular 6 - MEAN Stack Crash Course - Part 1: Front-end Project Setup And Routing",
https://www.youtube.com/watch?v=x2_bcCZg8vQ -
"Angular 6 - MEAN Stack Crash Course - Part 2: Implementing The Back-end",
https://www.youtube.com/watch?v=a30flH_q5-A&t=774s -
"Angular 6 - MEAN Stack Crash Course - Part 3: Connecting Front-end To Back-end",
https://www.youtube.com/watch?v=HTqghYMRrtA -
"ngular 6 - MEAN Stack Crash Course - Part 4: Completing The User Interface",
https://www.youtube.com/watch?v=PhIhNU5MLqo -
"Web Application Example of MEAN Stack",
https://github.com/hi1280/mean-example -
"Integrating Angular with Node.js RESTful Services",
https://github.com/DanWahlin/Angular-NodeJS-MongoDB-CustomersService -
"Node.js+express+MongoDB+Mongooseで簡単なjsonサーバを構築するメモ",
https://qiita.com/tdomen/items/4ecb15f25bf9c3652f59 -
"Mean stack の構築",
https://qiita.com/baster/items/5b6a2e49030067b6e55c -
"MEAN Stack Angular 6 CRUD Web Application",
https://www.djamware.com/post/5b00bb9180aca726dee1fd6d/mean-stack-angular-6-crud-web-application
Express
-
"サルでも分かるExpressでのjsonAPIサーバーの作り方",
https://qiita.com/leafia78/items/73cc7160d002a4989416 -
"Node.js, Express, sequelize, React で始めるモダン WEB アプリケーション入門(Express/sequelize編)",
https://qiita.com/tatsurou313/items/2ba0387806b07f442b8c -
"[Express] Expressの開発環境構築~デバッグ環境構築",
https://qiita.com/ksh-fthr/items/c22dedbc0952bfdcc808
MongoDB
-
"MongoDB + mongo-expressをDocker Composeでお手軽構築",
https://qiita.com/gldn/items/2a8486c4d7a42d7a0f1f -
"Cannot connect to MongoDB via node.js in Docker",
https://stackoverflow.com/questions/44938344/cannot-connect-to-mongodb-via-node-js-in-docker
Docker
-
"Docker Community Edition for Windows",
https://store.docker.com/editions/community/docker-ce-desktop-windows -
"Docker/Kubernetes 実践コンテナ開発入門",
http://amazon.co.jp/o/ASIN/4297100339/ -
"プログラマのためのDocker教科書 第2版 インフラの基礎知識&コードによる環境構築の自動化",
http://amazon.co.jp/o/ASIN/4798153222/ -
"Cannot link to a running container started by docker-compose",
https://stackoverflow.com/questions/36489696/cannot-link-to-a-running-container-started-by-docker-compose
Node.js
- "Node.js超入門[第2版] ",
http://amazon.co.jp/o/ASIN/4798055220/
Angular
-
"Containerizing Angular with Docker - Dan Wahlin",
https://www.youtube.com/watch?v=cLT7eUWKZpg&t=1140s -
"Deploy Angular 5 app in Docker Container in under 10 mins - For local development",
https://www.youtube.com/watch?v=L2UkQ2CND68&t=178s -
"Angular5, Angular6, Angular7 Custom Library: Step-by-step guide",
https://www.udemy.com/angular5-custom-library-the-definitive-step-by-step-guide/ -
"Angular5, Angular6, Angular7用 カスタムライブラリの作成: 完全ステップ・バイ・ステップ・ガイド",
https://www.udemy.com/angular5-l/