Nuxt + ExpressでDockerの状態を見てみる

## 自己紹介 
[Ateam Lifestyle Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-lifestyle) の7日目は 
株式会社エイチームライフスタイル 名古屋開発部でエンジニアとしてアルバイトをしている @takaHAL が担当します！



## 概要
Nuxt.js  と ExpressでAPIを作ってDockerの状態を取得してみます。

利用したもの　

- Nuxt.js  (v2.12.0)


- Vuetify.js

- Express


- Docker 

## プロジェクト作成
```
$ yarn create nuxt-app dockerstatus
```

いくつか質問されますが下記を選択しました

? Choose custom server framework


- Express

? Choose UI framework 

- Vuetify.js

ディレクトリ移動 します

```
$ cd dockerstatus
```
###  サーバー起動
```
$ yarn run dev
```

###  確認
#### Nuxt

下記にアクセス
http://localhost:3000/
画面が表示されました。
<img width="1440" alt="スクリーンショット 2019-11-27 14.45.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/d3b41116-b1c0-f7f8-0b58-98a99b5d0e54.png">

#### Express
デフォルトで作成されているindex.jsを見ます.

``` server/index.js
const express = require('express')
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
const app = express()

// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
config.dev = process.env.NODE_ENV !== 'production'

async function start () {
  // Init Nuxt.js
  const nuxt = new Nuxt(config)

  const { host, port } = nuxt.options.server

  // Build only in dev mode
  if (config.dev) {
    const builder = new Builder(nuxt)
    await builder.build()
  } else {
    await nuxt.ready()
  }

  // Give nuxt middleware to express
  app.use(nuxt.render)

  // Listen the server
  app.listen(port, host)
  consola.ready({
    message: `Server listening on http://${host}:${port}`,
    badge: true
  })
}
start()
```

 `message: Server listening on http://${host}:${port}`
の内容がterminal上に出ていればOKです。
<img width="708" alt="スクリーンショット 2019-11-27 14.55.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/7497e2b5-3ded-4729-49f0-8f3447ea4cb4.png">

### ExpressでAPIを作成
docker psの内容を取得します.

``` server/index.js
// 追記
app.get('/dockerPs', function (req, res) {
  const ps = dockerPs()
  const psData = []

  ps.split(/\r?\n/g).forEach((item) => {
    if (item.length !== 0) {
      psData.push({
        id: JSON.parse(item).ID,
        names: JSON.parse(item).Names,
        status: JSON.parse(item).Status,
        ports: JSON.parse(item).Ports,
        running: JSON.parse(item).RunningFor
      })
    }
  })

  res.send({
    psData
  })
})

const dockerPs = () => {
  const execSync = require('child_process').execSync
  const data = execSync(
    '/usr/local/bin/docker ps --format "{{json .}}"'
  ).toString()
  return data
}
```
この状態で下記にアクセスしましょう
http://localhost:3000/dockerPs
僕の場合はMySQLの5.6と5.7を使用しているため下記のような結果が得られました。



<img width="1440" alt="スクリーンショット 2019-12-03 0.41.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/07c912b7-0d1c-dcc6-fa60-1f6e8ff0d3a6.png">

今回作成したAPIを叩くと結果がJSON形式で帰ってきます




### Nuxt側からAPIを叩く！
index.vueに記述していきます。

``` pages/index.vue
<template>
  <v-layout
    column
    justify-center
    align-center
  >
    <v-flex
      xs12
      sm8
      md6
    >
      <div class="text-center">
        <logo />
        <vuetify-logo />
      </div>
      <v-card>
        <v-card-title class="headline">
          Welcome to the Vuetify + Nuxt.js template
        </v-card-title>
        <v-card-text>
          <p>Vuetify is a progressive Material Design component framework for Vue.js. It was designed to empower developers to create amazing applications.</p>
          <p>
            For more information on Vuetify, check out the <a
              href="https://vuetifyjs.com"
              target="_blank"
            >
              documentation
            </a>.
          </p>
          <p>
            If you have questions, please join the official <a
              href="https://chat.vuetifyjs.com/"
              target="_blank"
              title="chat"
            >
              discord
            </a>.
          </p>
          <p>
            Find a bug? Report it on the github <a
              href="https://github.com/vuetifyjs/vuetify/issues"
              target="_blank"
              title="contribute"
            >
              issue board
            </a>.
          </p>
          <p>Thank you for developing with Vuetify and I look forward to bringing more exciting features in the future.</p>
          <div class="text-xs-right">
            <em><small>&mdash; John Leider</small></em>
          </div>
          <hr class="my-3">
          <a
            href="https://nuxtjs.org/"
            target="_blank"
          >
            Nuxt Documentation
          </a>
          <br>
          <a
            href="https://github.com/nuxt/nuxt.js"
            target="_blank"
          >
            Nuxt GitHub
          </a>
        </v-card-text>
        <v-card-actions>
          <v-spacer />
          <v-btn
            color="primary"
            nuxt
            to="/inspire"
          >
            Continue
          </v-btn>
        </v-card-actions>
      </v-card>
    </v-flex>
  </v-layout>
</template>

<script>
import axios from 'axios'
import Logo from '~/components/Logo.vue'
import VuetifyLogo from '~/components/VuetifyLogo.vue'

export default {
  components: {
    Logo,
    VuetifyLogo
  },
  asyncData () {
    axios.get('http://localhost:3000/dockerPs').then((res) => {
      console.log(res.data)
    })
  }
}
</script>

```
  下記が追記項目になります。

``` js
import axios from 'axios'
    .
    .
    .
export default {
    .
    .
    .
  asyncData () {
    axios.get('http://localhost:3000/dockerPs').then((res) => {
      console.log(res.data)
    })
  }
}
```

F12を押してconsoleを確認してみましょう

<img width="595" alt="スクリーンショット 2019-11-27 15.43.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/0beca43e-0eb4-5f93-4943-e1a31234a160.png">

取得できていますね。

### 利用しているDockerのコマンドについて
[参考](https://docs.docker.com/config/formatting/#json)

今回利用しているもの
`docker ps --format "{{json .}}"`
docker psコマンドの結果をJSON文字列としてエンコードしています。

## 成果物
これらの内容を元に以下のものを制作しました

コンテナの状態などを可視化したり
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/42b5cbff-936c-5fb9-675d-7c84751f8d54.gif)
ログを表示・検索したり
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/63878b23-734a-bdab-0b16-5b758daf95fe.gif)

Port番号などの情報を見たり
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/5c211d25-98fd-dd38-da16-ea0f14b9f895.gif)

コンテナの停止・起動・再起動をボタンで行うようにしたり
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/445600/517c8d04-f43f-9c34-228a-de12bd725e67.gif)


## まとめ
自分の手でコマンドから得た結果を可視化してみるというのはとても楽しくDockerへの理解も少し深まり、Dockerのコマンドを色々と調べるいい機会にもなりました。
また、今回僕は使いませんでしたが[Grafana](https://grafana.com/)というものを使えば見た目もかっこいい感じに作れるみたいなので使ってみても面白いかもしれません
















 









[Ateam Lifestyle Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ateam-lifestyle) の 8日目は、@snd-07 がお送りします！！どんなネタを用意してくるのか楽しみです！！

そんな"挑戦"を大事にするエイチームグループでは、一緒に働けるチャレンジ精神旺盛な仲間を募集しています。興味を持たれた方はぜひエイチームグループ採用サイトを御覧ください。
https://www.a-tm.co.jp/recruit/