[Docker, Node.js] Node.jsアプリを Docker に投入する

今回のサンプル

import pexpress from 'express';
const oapp = pexpress();

oapp.get('/', (req, res) => {
  res.send('Docker test');
})

oapp.listen(3000, () => {
  console.log('listen 3000....');
})

シンプルにexpress で待機するだけのアプリ

  • Node.js v18 で確認
  • ESModule の記述となるので、後述の package.json 編集にて「type:module」を追記することになる

package.json

特にDocker用に編集する内容は無い

  • “type”:”module” を追記して ESModule に対応させる

Dockerfile

FROM node:18
WORKDIR /usr/src/testapp
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD [ "node", "./src/main.js" ]
  • FROM : このアプリを構成するために必要なイメージ、必ず最初に指定する
  • WORKDIR: 一時作業用のディレクトリ、作業後は削除されるのでどこでも良い
  • COPY : コピーしたい元ファイル と、作業用ディレクトリに送る先を記述し、ファイルをコピーする
  • RUN : 何らかのコマンドを実行する
  • EXPOSE : コンテナ実行時にlisten するポートを Docker へ明示的に指定する
  • CMD : コンテナ実行時のデフォルト命令

参考にした手順はこちら
Node.js Web アプリケーションを Docker 化する | Node.js (nodejs.org)

他にも命令はある
詳細はリファレンス参照
Dockerfile リファレンス — Docker-docs-ja 20.10 ドキュメント

Q. [Dockerfile] CMD のコマンド指定について

Dockerfile リファレンス — Docker-docs-ja 20.10 ドキュメント
通常のコマンドラインのような指定も可能ではあるが、
ドキュメントによれば JSON配列形式のほうが望ましいとある
JSON配列形式 の場合、シェルを使わず実行する様子

Q. [Dockerfile] なぜ package*.json のコピーを先行する?

Node.js Web アプリケーションを Docker 化する | Node.js (nodejs.org)
こちら中ほどに記載されている
曰く「キャッシュされた Docker レイヤーを利用することができます」 とのこと
詳細は記述されているリンク参照

Building Efficient Dockerfiles – Node.js – bitJudo

つまりどういうことかというと、「常に最初からすべてのモジュールをダウンロードしなおすと手間がかかるので、
キャッシュ使ってデプロイを効率化しよう」という動きができるとのこと
効果は後述の「Q. アップデートするには」にて記載

.dockerignore

node_modules

他無視したい事項を、.gitignore のように記述
node_modules は Docker 側で改めて落としてもらうので、必ず無視するよう指定する

イメージ作成

Windowsの場合 Docker Desktop を用いるが、
私はこれ以上汚くインストールするソフトを増やしたくない(切実)ので、
Dockerの入っている Alma Linux 9 で作業を行う

もちろん、そういうのを気にしない人は Docker Desktop を導入して Windowsにてイメージ化し、
サーバーにはイメージを転送すると良い

  • Alma Linux 9 に 作ったアプリをフォルダごとアップロード
  • 下記コマンドを実行
docker build . -t (タグ名)

portainer.io でイメージを確認するとこんな感じ

イメージからコンテナ作成

  • Name : 任意
  • Image : つけたタグ
  • Always pull the image : 外す ※docker.io にもし存在していたら上書きされそう
  • Manual network port publishing
    • 3000/tcp ⇒ 3000/tcp

テスト

Express の / にアクセスすると 指定した文字列が返される
ブラウザでなくても、サーバーで curl http://localhost:3000 などでもテスト可能

Q. アップデートするには?

  • docker build を同じタグで行う
  • portainer.io の場合、コンテナの「Duplicate/Edit」から同じパラメータのまま「Deploy the container」
    • 「Always pull the image」を外すこと

再度イメージ化する際はキャッシュが使われている様子が見える
これは先述の package*.json を先にコピーすることから得られる効果

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Share via
Copy link