【備忘録】Express環境を作る (Docker,TypeScript対応あり)

Express の環境を以下の手順で行ってゆく

- ローカルでExpressアプリケーションを構築
- Type-Scriptで動作できるようにする
- ファイル変更時に自動的に再ビルドが走るようにする
- Dockerのコンテナ化


## ローカルでExpressアプリケーションを構築

アプリケーションディレクトリを作成する
```sh
mkdir express && cd express
```

node.jsをインストール
```sh
npm install node
```

package.jsonを生成 (Node.js プロジェクトの初期設定)
```sh
npm init -y
```
`-y`オプションはすべてデフォルトの設定で行うという意味

Expressのインストール
```sh
npm install express
```

index.jsを作成
```sh
touch index.js
```
```index.js
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => {
    res.send('Hello, Express in Docker!');
});

app.listen(port, '0.0.0.0', () => {
    console.log(`Server is running at http://localhost:${port}`);
});
```

サーバーを起動する
```sh
node index.js
```
http://localhost:3000 にアクセスして「Hello, Express!」と表示されればここまで完了です。


## Type-Scriptで動作できるようにする
[`ローカルでExpressアプリケーションを構築`が完了していることが前提です。]

Type-Script関係のライブラリをインストール
```sh
npm install -D typescript ts-node @types/node
npm install -D @types/express
```
tsconfig.jsonの作成
```sh
npx tsc --init
```

先ほど作った`index.js`をTypscriptように`index.ts`に置き換える
```index.ts
import express, { Request, Response } from "express";

const app = express();
const port = 3000;

app.get("/", (req: Request, res: Response) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});
```

package.jsonを編集
```diff_json
  "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "start": "ts-node index.ts"
  }
  ```

  サーバーを起動する(コマンドが変わるので注意)
```sh
npm run start
```
http://localhost:3000 にアクセスして「Hello, Express!」と表示されればここまで完了です。

## ファイル変更時に自動的に再起動が走るようにする

nodemonをインストール
```sh
npm install -D nodemon
```

tsconfig.jsonを編集する
```diff_json
{
  "compilerOptions": {
  ...
-   // "outDir": "./",   
+   "outDir": "./dist/"
  ...
  }
}

package.jsonを編集
```diff_json
  "scripts": {
-    "start": "ts-node index.ts"
+    "start": "nodemon dist/index.js",
+    "build": "npx tsc",
+    "build:watch": "npx tsc",
+    "dev": "npm run build:watch & npm run start"
  }
  ```

  サーバーを起動する(コマンドが変わるので注意)
```sh
npm run dev
```
http://localhost:3000 にアクセスして「Hello, Express!」と表示されればここまで完了です。

ファイル変更時に`npm run dev`を実行すると、自動的に再ビルドされた後、サーバーも再起動され、変更が反映されます。


## Dockerのコンテナ化

Dockerfileの作成
```DOckerfile
FROM node:18.19.1

WORKDIR /usr/src/express

COPY package*.json ./
RUN npm install

COPY . .
```
docker-compose.ymlの作成
```docker-compose.yml
services:
  express:
    container_name: express
    build:
      context: ./express_src # package.jsonまでの相対パスにする
      dockerfile: ../docker/express/Dockerfile # Dockerfileまでの相対パスにする
    volumes:
      - /usr/src/node_modules
      - ./express_src:/usr/src/express # <expressアプリケーションディレクトリまでの相対パス : Dockerfileで決められたコンテナ内のパス> の形式にする
    command: npm run dev
    expose:
      - 3000
    ports:
      - "3000:3000"
```
<font color="DimGray">
TypeScriptや自動再起動設定の工程をスキップした場合は</font> 
command:
<font color="DimGray">
の部分を適宜サーバー起動コマンドに置き換えてください。</font>
</font>

dockerコンテナをビルド
```sh
docker compose up -d --build
```
docker コンテナを起動
```sh
docker compose up -d
```

http://localhost:3000 にアクセスして「Hello, Express!」と表示されれば全過程完了です。
お疲れ様でした。


次回以降は下記コマンドのみで起動できます。
```sh
docker compose up -d 
```
----
### 参考資料
https://qiita.com/omukaik/items/ac092a07e5575d07e1f9