IT研修でVuePress+Nuxt on Dockerでシステムを作成した話

2019/10/12

2018/04/29投稿ではてなブログから移行した内容です.

雑談

前回の投稿から1ヵ月...
入社して1ヵ月が経ち,現在はIT研修を受けている日々.
今回は,そのIT研修で作成したブログシステムについて話していく.

最終成果物はこちら
ソースコードはGitHubのこちら

この記事で話す内容

  • このシステムはどんな構成で,どういう形で動いているのか
  • これを作成するに当たり,ぶつかった大きな4つの壁

    • リアルタイム性のあるDocker環境を作成できない
    • Docker環境で立ち上げたNuxtがホスト側からアクセスできない
    • VuePressのサイドバーは自分で設定しないといけない
    • Windows特有のDockerエラー
  • このシステムを作ってみて,わかったことなど所感

技術構成

VuePressで記事を表示.
Nuxtで管理画面を表示し,記事を登録した際に,ExpressにPostして,
ExpressがVuePressのdocsにフォルダと記事の内容が書いてあるREADME.mdを作成.
編集画面を開くと,NuxtからExpressにGetし,ExpressがVuePressのdocsフォルダから情報を取得.
という流れ.

20180429172257

フォルダ構成

root/
├ docs/ ←VuePress
│     ├ .vuepress/
│     │      ├ public/
│     │      └ config.js
│     ├ about/←記事
│     ├ back/  ←記事
│     └ README.md
│ 
├ nuxt/ ←Nuxt
│     ├ Nuxtのフォルダなど(省略)
│     └ Dockerfile
│ 
├ docker-compose.yml
├ Dockerfile
└ index.js ←Express

リアルタイム性のあるDocker環境を作成できない

最初は,DockerfileでホストのrootをDocker環境にCOPYコマンドでコピーを行っていた.
しかし,これだと複数の問題点がある.

  • ホスト側を修正してもDocker側には影響がないため,コンテナを立て直す必要がある
    ※これだと毎回コンテナが立ち上がる時間を待つ必要があり,結果をすぐ見ることができない.
  • Docker環境側のファイルを修正する
    ※これだとコンテナを落とすと編集したものが消えてしまう.
    解決策としてDocker環境のファイルをホスト側にコピーする.
    これはとてもナンセンス

解決策

マウント機能を使う.
docker-compose.yml内で
volums:
- ホスト側:Docker側

Dockerコマンドの引数で指定できるみたいだが,面倒だったのでDocker Composeを導入した.

Dockerfile

FROM node:9.1.0

RUN useradd --user-group --create-home --shell /bin/false app

ENV HOME=/home/app

COPY package.json $HOME/press/
RUN chown -R app:app $HOME/*

USER app
WORKDIR $HOME/press
RUN yarn

CMD ["yarn", "start"]

docker-compose.yml

version: "3"
services:
  press:
    build: .
    ports:
      - '8080:8080'
      - '3000:3000'
    volumes:
      - .:/home/app/press
      - /home/app/press/node_modules
    container_name: 'press'

Node.jsでの開発の主流?はこういう流れっぽい(適当)

  1. ホスト側のpackage.jsonをDocker環境へコピー
  2. Docker環境内でpackage.jsonに記述されているモジュールをインストール (npm install)
  3. Docker環境下にホストの環境をマウント
  4. node_modulesがホスト側に作成されないように,volumesでDocker環境内に閉じ込める

Docker環境で立ち上げたNuxtがホスト側からアクセスできない

Docker環境でNuxtを立ち上げると,ちゃんと127.0.0.1:3000で立ち上がったと出てくる.

しかし,ホストで立ち上げたようにブラウザにlocalhost:3000にアクセスしても表示されない...

解決策

127.0.0.1は自分のIPを指してる(詳しくは調べてね)ので,Dockerfileに0.0.0.0を設定してあげる.

実際のNuxt用のDockerfile

FROM node:9.1.0

RUN useradd --user-group --create-home --shell /bin/false app

ENV HOME=/home/app

COPY package.json $HOME/nuxt/
RUN chown -R app:app $HOME/*

USER app
WORKDIR $HOME/nuxt
RUN yarn

ENV HOST 0.0.0.0

CMD ["yarn", "dev"]

※追記 2018年5月3日

Nuxt on Docker for Windowsの場合,ホットリロードがうまくいかない.

なので,nuxt.config.jsに記述してあげる必要がある.

  watchers: {
    webpack: {
      poll: true
    }
  }

VuePressのサイドバーは自分で設定しないといけない

VuePressは,サイドバーに表示する内容を,root/docs/.vuepress/config.jsに書き込まないといけない.

でも,今回は管理者画面からフォルダとREADME.mdを作成するというものになっているため,

サイドバーに表示する内容は自動で行う必要がある.

解決策

サイドバーの情報をArray型の変数にする.

その変数に,ディレクトリ情報を取得して,名前を入れていく形

config.js

const fs = require('fs');
const path = require('path');

var dirpath = "./docs"
var dirs = fs.readdirSync(dirpath).filter((f) => {
  return fs.existsSync(dirpath + "/" + f) && fs.statSync(dirpath + "/" + f).isDirectory()
})

let sidebarItems = ((dirs) => {
  let items = ['/']
  dirs.forEach((d, index) => {
    if (d !== '.vuepress' && d !== 'admin') {
      items.push('/' + d + '/')
    }
  })
  return items
})(dirs)

module.exports = {
  title: 'Death March',
  description: '社内ドキュメントを管理',
  themeConfig: {
    sidebar: sidebarItems,
    nav: [
      {
        text: 'about',
        link: '/about/',
      },
      {
        text: 'admin',
        link: 'http://localhost:8888'
      }
    ],
  }
}

Windows特有のDockerエラー

エラー

ERROR: Service 'press' failed to build: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

解決策

  1. タスクバー?のDockerアイコンを右クリック
  2. Settings...をクリック
  3. Networkタブに移動
  4. DNS ServerをFixedにチェック
  5. 8.8.8.8に設定

他にも,何のエラーが出るのか忘れたが,DaemonタブのExperimental featuresにチェックが入っていると,

これもWindows特有の悪さをするみたいなので,チェックを外しておこう.

所感

2週間でブログシステムを作るという課題で, 自分が初めての技術も取り入れつつ, 完成させることができたのは本当によかった.
Dockerfileを使う側から作る側にも慣れたし, VuePressというまだ情報が少ないもの(リリース2週間)も使うことができたし, とてもエンジニアらしい感じのことができて満足.
これから, どんどん新しい知識を入れていきたいと思います.