今回のサンプル
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 を先にコピーすることから得られる効果