Ishida-IT LLC

< Back

DockerでNode.jsアプリケーションを開発する (1) Express.jsをコンテナ内で動かす

Posted: 2019-11-20

Dockerを使って、PC本体になるべく何もインストールせず、複数の開発者間で統一された環境でアプリケーションの開発が出来るようにしたいと思います。

PC本体(以下ホスト)側には、「Docker Desktop」と「VS Code」だけをインストールします。

動作検証は Mac(macOS Mojave 10.14.6)で行っていますが、Windows環境やLinux環境でも問題なく動くはずです。



1. Docker DesktopとVS Codeをインストール

Dockerは下からダウンロードしてインストールします。

Docker Desktop for Windows
https://hub.docker.com/editions/community/docker-ce-desktop-windows

Docker Desktop for Mac
https://hub.docker.com/editions/community/docker-ce-desktop-mac


VS Codeは下からダウンロードしてインストールします。
https://code.visualstudio.com/download




2. プロジェクトのフォルダを作成

> mkdir docker-nodejs
> cd docker-nodejs
> mkdir src

上のコマンドを実行して次のようなフォルダ構成を作ります。

docker-nodejs
  └── src/

プロジェクトのルートフォルダ直下にはDocker(docker-compose)に関する設定ファイルなどを配置し、アプリケーション本体は/src/フォルダ内に作成することにします。




3. docker-compose.ymlファイルを作成

Node.jsアプリケーションをDockerコンテナ内で動かすには、下のページが参考になります。

Dockerizing a Node.js web app | Node.js
https://nodejs.org/ja/docs/guides/nodejs-docker-webapp/

ただ、今回はNode.jsの公式イメージを使ってコンテナを起動するのでDockerfileを書いて独自のイメージを作成する必要がありません。なのでDockerfileなしでdocker-compose.ymlに各種の設定を記述し、これを使ってアプリケーションを動かす方法をとることにします。

プロジェクトのルートフォルダに下の内容でdocker-compose.ymlファイルを作成します。

version: '3'
services:
  app:
    # 起動するイメージを指定(ここではNode.js v12の公式イメージ)
    image: node:12    

    # 環境変数を設定
    environment:
      - DEBUG=app:*

    tty: true

    # ホスト側のポート:コンテナのポート
    ports:
      - '3000:3000'   

    # ソースコードを格納するフォルダをマウント
    #(ホスト側の./srcをコンテナの/appにマウント)
    volumes:
      - ./src:/app    

    # 起動時のカレントフォルダを指定
    working_dir: /app   

    # 起動後に実行するコマンドを指定
    command: npm start  



4. Node.jsコンテナを起動してコンテナ内でExpress.jsアプリケーションを作成する

docker-compose runコマンドで一時的にコンテナを起動して、/appディレクトリ内でExpress.jsアプリケーションの初期化を行います。 ホストPC側ではなくコンテナ内で行うのは、下の理由からです。

  1. ホストPCにNode.jsがインストールされていなくても実行可能。
  2. 依存パッケージがネイティブモジュールを含む場合に、ホスト側でnpm installを行うとコンテナ内で動かない可能性がある。
# Node.jsコンテナを一時的に起動
> docker-compose run --rm app /bin/bash

    =====(ここからコンテナ内)=====
    # lsコマンドで/appディレクトリ(=ホスト側の./src)内にまだ何も無いことを確認
    ls -al

    # express-generatorでアプリケーションのひな形を生成
    npx express-generator

    # 依存パッケージをインストール
    npm install
    =====(ここまでコンテナ内)=====

express-generator.png

npm installまで正常に出来たら、CTRL+dを押してコンテナから抜けます。

docker-compose runコマンドに「–rm」オプションを付けているので、抜けた時点で自動的にこのコンテナは削除されますが、作成されたフォルダやファイルはホスト側のsrcフォルダにマウントされているので消えることはありません。




5. docker-compose upでアプリケーションを起動する

下のコマンドでアプリケーションを起動します。 docker-compose.ymlファイル内で「command:」に「npm start」を設定してあるので、コンテナ起動後自動的にExpress.jsのアプリケーションがスタートします。

> docker-compose up

ホスト側でブラウザを開いて http://localost:3000 にアクセスし、Express.jsの画面が表示されればOKです。

expressjs.png


6. ソースコード変更時にアプリケーションが自動で再起動されるようにする

ここまででDockerコンテナ内でアプリケーションが動くようになりました。

ただ、このままだとソースコードを編集してそれを反映するためには、毎回コンテナを停止・再起動する必要があります。

それでは不便なので、ソースコードの変更を検知して必要な時にアプリケーションを再起動してくれる、「nodemon」というツールをインストールします。

「docker-compose up」でコンテナが起動したままの場合は、CTRL+cを押して停止しておいてください。

もし

> docker-compose up -d

のように「-d」オプションを付けてバックグラウンドでコンテナを起動していた場合は、

> docker-compose stop

で停止出来ます。

Node.jsコンテナを一時的に起動

> docker-compose run --rm app /bin/bash

コンテナ内でnodemonをインストール

    =====(ここからコンテナ内)=====
    npm install -D nodemon
    =====(ここまでコンテナ内)=====

※上の2つのステップは次のコマンドで一気に実行することも出来ます。

> docker-compose run --rm app npm install -D nodemon

src/package.jsonの「scripts」に”dev”を追加

  "scripts": {
    "dev": "nodemon ./bin/www",
    "start": "node ./bin/www"
  },

docker-compose.ymlファイルを編集

    (変更前)
    command: npm start

    (変更後)
    command: npm run dev

コンテナを起動

> docker-compose up -d

起動後「npm run dev」が自動的に実行されます。

これによって、ソースコードを変更した時にコンテナ内でNode.jsのプロセスが再起動されて、変更内容が数秒で反映されるようになります。

上のように「-d」オプションを付けた場合は、コンテナがバックグラウンドで起動されます。その場合は「docker-compose logs -f」を使うとコンテナで出力されるログを確認することが出来ます。

> docker-compose logs -f

nodemon.png

コンテナの停止は、

> docker-compose stop

停止および削除は、

> docker-compose down

で行えます。



さて、この状態でも十分実用的に開発出来るようになっているのですが、ホスト側からNode.jsのコードにブレークポイントを設定してアプリケーション実行中に変数の内容を確認したりするようなことは出来ません。そのような機能を実現するためには、VS Codeのリモート拡張機能を使う必要があります。これについては次回の記事で書きたいと思います。

ソースコード

プロジェクトの現在の状態の全ソースコードは、下のURLで確認出来ます。

https://github.com/ishidait/docker-nodejs/tree/blog-1



次回

DockerでNode.jsアプリケーションを開発する (2) VS Codeのリモート拡張機能を使う
https://ishida-it.com/blog/post/2019-11-22-docker-nodejs/