3
3

はじめに

この記事では、Dockerfile からビルドしたイメージを元に Node.js / TypeScript のコンテナを作成する手順について記載します。

以下の記事の Node.js / TypeScript バージョンです。

開発環境

開発環境は以下の通りです。

  • Windows11
  • Docker Engine 26.1.1
  • Node.js 20.15.1
  • npm 10.8.2
  • @types/node 20.14.10
  • ts-node 10.9.2
  • TypeScript 5.5.3

Node.js / TypeScript アプリケーションの作成

まずは、Node.js / TypeScript アプリケーションを作成します。

package.json の作成

package.json を作成します。

コマンド実行中の質問をスキップするため、-y をつけて実行します。

npm init -y

package.json が作成されます。

package.json
{
  "name": "node",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}

TypeScript のインストールと設定

TypeScript 及び以下のパッケージをインストールします。

  • ts-node : TypeScript を Node.js で直接実行できるようにする
  • @types/node : Node.js の型定義

npm install typescript ts-node @types/node --save-dev

package.json にインストールしたパッケージが表示されます。

package.json
{
  ...
  "devDependencies": {
    "@types/node": "^20.14.10",
    "ts-node": "^10.9.2",
    "typescript": "^5.5.3"
  }
}

また、node_modules が作成されるので .gitignore を作成し、node_modules を追加して、git 管理対象外とします。

.gitignore
node_modules

次に TypeScirpt 設定ファイルを作成します。

npx tsc --init

tsconfig.json が作成されます。

デフォルトでは、CommonJS を利用する設定になっていますが、ES Modules (ECMA Script Modules) を利用したいので、設定を変更します。今回は Node.js 20 系を利用するので、20 系に対応した libmoduletarget を指定します。

tsconfig.json
{
  "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 ファイルを作成し、ログを出力するコードを実装します。

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 でエントリーポイントの変更とアプリケーションを実行するスクリプトの追加を行います。

package.json
{
  ...
  "main": "src/index.ts",
  "scripts": {
    "start": "ts-node src/index.ts",
    ...
  ...
}

スクリプトを実行して、一度動作確認します。

npm start

実装通りログが表示されることを確認します。

image.png

Dockerfile の作成

Dockerfile を作成し、イメージをビルドします。

ベースイメージ FROM

ベースイメージはタグが 20-alpine3.19 の Node.js イメージを利用します。

FROM node:20-alpine3.19

作業ディレクトリ WORKDIR

作業ディレクトリを /app にします。

WORKDIR /app

デフォルトでもルートディレクトリ(/)が作業ディレクトリとなるので、このインストラクションは任意です。ただ、作業ディレクトリを指定することで、Dockerfile のこれ以降の COPYRUN などのインストラクションによって生成されるディレクトリやファイルが app 内に配置されます。そのため、コンテナ内の他のファイルと区別しやすくなります。

ホストマシンのファイルをコピー COPY

ホストマシンの package.json 及び package-lock.json をコンテナの作業ディレクトリにコピーします。

COPY package*.json ./

現時点で本インストラクションを記載しておくことで、次に実施する依存関係のインストールでキャッシュを利用でき、ビルドスピードが向上します。
package.jsonpackage-lock.json に変更があった時だけイメージビルド時、依存関係がインストールされます。

依存関係のインストール RUN

先ほどコピーした package.json に記載されたパッケージ及びその依存関係をコンテナにインストールします。

RUN npm install

ホストマシンの全ファイルをコピー COPY

ホストマシンの全ファイルをコンテナの作業ディレクトリにコピーします。

COPY . .

コンテナのポートを指定 EXPOSE

3000 ポートを開けます。

EXPOSE 3000

コンテナ起動時のコマンドを指定 CMD

コンテナ起動時に package.jsonscriptsstart を実行します。

CMD ["npm", "start"]

イメージのビルド

完成した Dockerfile は以下の通りです。

FROM node:20-alpine3.19
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

こちらの Dockerfile からイメージをビルドします。

docker image build --tag node-app:0.0.1 .

image.png

イメージがビルドできたか確認します。

docker image ls node-app

image.png

コンテナの起動

ビルドしたイメージからコンテナを起動します。

docker container run `
--name app           `
--rm                 `
--publish 3000:3000  `
node-app:0.0.1

Dockerfile 作成前にホストマシンで動作確認したときと同じログが表示されます。

image.png

参考

関連リンク

3
3
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
3
3