LoginSignup
10
8

More than 5 years have passed since last update.

DockerでMEAN Stackの稼働環境を簡単実現

Last updated at Posted at 2019-01-02

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_onlinksの使い方がよくわかっていなかったからによります。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

Express

MongoDB

Docker

Node.js

Angular

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8