NodejsでWebアプリケーション作成 with Docker

# 前提
ProgateのNodejsコース完了程度の知識があること。
Docker使える。
[VSCodeでDocker入門](https://qiita.com/Teach/items/ca09b8882f519dca600c)

# 本記事の対象者
ProgateでNodejs学んだ。次は自分のプロジェクトを作ってみたいって人

# 本記事でやること

- DockerでNodejs環境を作る
- プロジェクトの作成
- ライブラリのインストール
- ブラウザ上でページを確認

# 環境
Docker
VSCode
Node 14.15
Git

# プロジェクトの作成

まず適当な場所にプロジェクトのフォルダを作成。
本記事では `nodejs-sample-app` という名前で作った。

そして、そのフォルダをVSCodeで開く。

以下のファイルを作成

```docker-compose.yml
version: "3"
services:
  node:
    image: node:14.15
    volumes:
      - .:/project
    tty: true
    working_dir: /project
    command: bash
```

Nodeのバージョンは14.15を指定しておく。



コンテナに入ってバージョンを確認。

```
root@cf2295d42525:/project# node -v
v14.15.4
```

そしたらプロジェクトを作る準備が完了。


ここからnpmコマンドを使ってプロジェクトを構築する。

以下のコマンドを打つと、プロジェクトに `package.json`というファイルが作成される。
```
$ npm init -y
```

[npm init リファレンス](https://docs.npmjs.com/cli/v6/commands/npm-init)

```
root@cf2295d42525:/project# npm init -y
Wrote to /project/package.json:

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

package.json は Nodejsプロジェクトの様々な情報をかくところと把握しておけばOK

次に Webアプリケーション において一番最初に呼ばれるjsファイルを作る。
package.json と同じ階層に以下のように作成

```app.js
console.log("Hello nodejs");
```

そうしたら、以下のコマンドで実行されるか確かめる

```
root@cf2295d42525:/project# node app.js
Hello nodejs
```
Hello nodejs と表示されたらOK


次に package.json を以下のように変更

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

```
mainを修正 testの末尾にカンマ追加, scripts.start追加

そうすると、 `npm start`でscripts.startで指定したコマンドが呼ばれるようになる。

```
root@cf2295d42525:/project# npm start

> project@1.0.0 start /project
> node app.js

Hello nodejs
```

これでひと段落。

このタイミングで`git init`すると良い。

# expressのインストールとルーティング

expressのインストール

```
$ npm install express
```

package.jsonに以下のように追記される

```
{
...
  "dependencies": {
    "express": "^4.17.1"
  }
}

```

そして、node_modulesというフォルダと package-lock.jsonというファイルができる。

node_modulesにはインストールしたpackageが入る。
これはプッシュしたくないのでgitignoreを作成してつっこむ。

```:.gitignore
node_modules/
```

![スクリーンショット 2021-01-09 19.24.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/55a99f92-de87-2b90-5290-21968a584b85.png)

installして差分がでてるのでここでcommit。

ルーティングを作成

```app.js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send({message: "ok!"});
});

const port = process.env.PORT || 3000
app.listen(port, () => console.log(`server started port ${port}`));
```

`npm start`すると、以下のように表示される。

```
root@cf2295d42525:/project# npm start

> project@1.0.0 start /project
> node app.js

server started port 3000
```

しかし、今のままではブラウザでひらけない

![スクリーンショット 2021-01-09 19.30.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/0913bc2d-b1de-5dd0-406c-dd7d1334e702.png)

docker-composeにportについて記述する必要がある。

```docker-compose.yml
version: "3"
services:
  node:
    image: node:14.15
    volumes:
      - .:/project
    tty: true
    working_dir: /project
    ports:
      - "3000:3000"
    command: npm start
```

portsを追加し、コンテナを立ち上げた時に npm start 実行するように変更した。

docker-compose を編集したら、コンテナを作り直す必要がある。
一度コンテナを消して以下を実行

```
$ docker-compose up -d
```

ちゃんとサーバーとして起動しているかログを確認

```
nodejs-sample-app(main)$ docker-compose logs       
Attaching to nodejs-sample-app_node_1
node_1  | 
node_1  | > project@1.0.0 start /project
node_1  | > node app.js
node_1  | 
node_1  | server started port 3000
```

いけてそう。

ブラウザで確認

![スクリーンショット 2021-01-09 19.34.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/5744c07d-8c34-2f1b-a2ec-ea8d26fe0423.png)


# ejs

ejsを使うためにインストール
```
$ npm install ejs
```

viewsフォルダを作成し、その中にejsファイルを作成

```html:views/index.ejs
<!DOCTYPE html>
<html lang='en'>
<head>
    <meta charset='UTF-8'>
    <meta name='viewport' content='width=device-width, initial-scale=1.0'>
    <title>Document</title>
</head>
<body>
    <p><%= message %></p>
</body>
</html>
```

```app.js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.render("index.ejs", {message: "うおおおおおお"})
});

const port = process.env.PORT || 3000
app.listen(port, () => console.log(`server started port ${port}`));
```

renderでejsを描画し、「message」を埋め込む

![スクリーンショット 2021-01-09 23.05.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/84a1d4c4-c37f-dc13-21cd-afd8277dc121.png)