TypeScript×Express×Dockerの開発環境構築

## 概要

Typescript×Express×Dockerを使ったサーバーサイド開発を行うための環境構築のメモです。まずローカル環境で開発できる環境を作成してから、Docker上でサーバーを起動できる環境を作成します。開発環境はMacです。

## まずローカル開発環境を作成してみる


### voltaによるnodeのインストール

- node.jsのバージョン管理ツールとして最近使われていそうだったvoltaを使用
  - https://volta.sh/

- homebrewを使用してインストール
```shell
$ brew install volta
```

- パスの自動追加
```shell
$ volta setup
```

- nodeのインストール。バージョンを指定しなければ最新LTSバージョンになる
```shell
$ volta install node
$ node -v
> v16.17.0
```


### express projectの作成（expressのインストールまで）

- expressのチュートリアルに従いアプリケーションの初期化を実行
  - https://expressjs.com/en/starter/installing.html

```shell
$ mkdir express # アプリケーションのディレクトリ作成
$ cd express
$ npm init　# package.jsonが生成される
$ npm install express
```

- pacage.jsonと、package-lock.jsonが生成される

```json:package.json
{
  "name": "expres",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.1"
  }
}
```

### typescriptの環境構築

- 必要なライブラリのインストール
```shell
$ npm install -D typescript ts-node @types/node
$ npm install -D @types/express
```

- tsconfig.jsonの作成
```shell
$ npx tsc --init
```

```json:tsconfig.json
{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}
```


### express projectの作成（hello worldまで）
- expressのチュートリアルに従いアプリケーションを起動できるところまで進める。jsファイルで書かれているため、Typescript用に手を加えています
  - https://expressjs.com/en/starter/hello-world.html

```typescript: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}`);
});
```

- scriptの追加
```json:package.json
  "scripts": {
    "start": "ts-node index.ts"
  }
```

- サーバの起動
    - 起動後 `http://local:3000` ブラウザ上などからでアクセスできることを確認する

```shell
$ npm run start
```

## ファイル修正時に自動的にアプリケーションの再起動を行うように設定する

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

- tsconfig.jsonに下記を追加する

```json:tsconfig.json
"outDir": "./dist/"
```

```json:tsconfig.json
  "scripts": {
    "start": "nodemon dist/index.js",
    "build": "npx tsc",
    "build:watch": "npx tsc",
    "dev": "npm run build:watch & npm run start"
  },
```

-下記のコマンドを実行することでファイル編集時にビルド&サーバーの再起動が行われるようになる
```shell
$ npm run dev
```

## Docker上で動かしてみる

### Dockerfileの作成

```dockerfile
FROM node:16.17

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm install

COPY . .
```

### docker-composeファイルの作成

- volumesの設定を行なっているので、ローカルのファイル変更をおこなった際にdocker環境上でも再ビルド&サーバーの再起動が行われる

```yml
version: "3"
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: app
    volumes:
      - /usr/src/node_modules
      - .:/usr/src/app
    command: npm run dev
    expose:
      - 3000
    ports:
      - "3000:3000"
```

- コンテナを立ち上げて　`http://localhost:3000` にブラウザでアクセスできる&ファイル編集時に変更が自動で反映されることが確認できます

```
$ docker-compose up
```


## 参考資料
- https://qiita.com/YoshinoriKanno/items/1a41b840a68dea2fb7e7
- https://expressjs.com/en/starter/installing.html
- https://qiita.com/zaburo/items/69726cc42ef774990279
- https://nodejs.org/ja/docs/guides/nodejs-docker-webapp/
- https://zenn.dev/ring_belle/articles/6266d2ea4651f9