はじめに
この記事では、Docker のバインドマウント機能を利用して、ホストマシンのファイルを Node.js コンテナで実行する手順について記載します。
以下の記事でも Node.js / TypeScript のコンテナを作成しましたが、このケースでは、ホストマシンのファイルに変更があった場合、都度イメージをビルドする必要があります。
バインドマウントを利用して、ホストマシンのファイルをコンテナで実行できるようにすることで、都度イメージをビルドする必要がなくなります。
開発環境
開発環境は以下の通りです。
- Windows 11
- Docker Engine 26.1.1
- Node.js 20.15.1
- npm 10.8.2
- @types/node 20.14.10
- nodemon 3.1.4
- ts-node 10.9.2
- TypeScript 5.5.3
Node.js / TypeScript アプリケーションの作成
package.json
を作成します。
npm init -y
TypeScript 及び以下のパッケージをインストールします。
-
ts-node
: TypeScript を Node.js で直接実行できるようにする -
@types/node
: Node.js の型定義
npm install typescript ts-node @types/node nodemon --save-dev
TypeScirpt 設定ファイルを作成します。
npx tsc --init
Node.js 20 系を、ES Modules
(ECMA Script Modules
) で利用する設定に変更します。
{
"compilerOptions": {
/* Language and Environment */
"target": "ES2022" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
"lib": [
"ES2023"
] /* Specify a set of bundled library declaration files that describe the target runtime environment. */,
/* Modules */
"module": "node16" /* Specify what module code is generated. */,
/* Interop Constraints */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
/* Completeness */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
src/index.ts
ファイルを作成し、ログを出力するコードを実装します。
import http from "http";
const HOSTNAME = "0.0.0.0";
const PORT = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader("Content-Type", "text/plain");
res.end("Hello World");
});
server.listen(PORT, HOSTNAME, () => {
console.log(`Server running at http://${HOSTNAME}:${PORT}`);
});
package.json
でエントリーポイントの変更とアプリケーションを実行するスクリプトの追加を行います。
{
...
"main": "src/index.ts",
"scripts": {
"start": "ts-node src/index.ts",
...
...
}
ここまでで、一度動作確認します。
npm start
実装通りログが出力されます。
Dockerfile の作成
Dockerfile を作成し、イメージをビルドします。
FROM node:20-alpine3.19
WORKDIR /app
COPY package*.json ./
RUN npm install
EXPOSE 3000
CMD ["npm", "start"]
今回ソースコードはバインドマウントしたホストマシンのファイルを利用するので、ホストマシンの全ファイルのコピー(COPY . .
)は不要です。
作成した Dockerfile からイメージをビルドします。
docker image build --tag node-ts:1.0.0 .
イメージがビルドできたか確認します。
docker image ls node-ts
コンテナの起動とバインドマウント
ビルドしたイメージを使ってコンテナを起動します。また、コンテナ起動時にホストマシンのファイルをバインドマウントします。
docker container run `
--name node-ts `
--rm `
--publish 3000:3000 `
--mount type=bind,source="$(pwd)",target=/app `
node-ts:1.0.0
実装したログが出力されます。
Node.js のバージョンを出力するログを追加して再度コンテナを起動します。
import http from "http";
const HOSTNAME = "0.0.0.0";
const PORT = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader("Content-Type", "text/plain");
res.end("Hello World");
});
server.listen(PORT, HOSTNAME, () => {
console.log(`Server running at http://${HOSTNAME}:${PORT}`);
console.log("node version is:" + process.version); // 追加
});
イメージを再ビルドしなくても Node.js のバージョンも出力されます。
参考
関連リンク