エンジニアの卵の成長日記

ふわっちで配信してますhttps://whowatch.tv/profile/w:kurowasi2525

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

前回の投稿から1ヵ月...

入社して1ヵ月が経ち,現在はIT研修を受けている日々.

今回は,そのIT研修で作成したブログシステムについて話していく.

最終成果物はこちら

ソースコードGitHubこちら

youtu.be

この記事で話す内容

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

課題

IT研修の課題で,2週間でブログシステムを作成するというものがあった.

条件は以下の2つ

  • 記事を閲覧する画面(ユーザ用)、記事を登録・編集・削除画面(ログイン有の管理者用)
  • HTML/CSS/JavaScriptjQuery・Node.js・MS SQLを利用する

技術構成

f:id:kurowasi2525:20180429172257p:plain

VuePress Express Nuxt
Docker press press nuxt
ポート 8080 3000 8888
機能 記事画面 API 管理画面

VuePressで記事を表示

Nuxtで管理画面を表示し,記事を登録した際に,ExpressにPostして,

ExpressがVuePressのdocsにフォルダと記事の内容が書いてあるREADME.mdを作成.

編集画面を開くと,NuxtからExpressにGetし,ExpressがVuePressのdocsフォルダから情報を取得.

という流れ.

フォルダ構成

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特有の悪さをするみたいなので,チェックを外しておこう.

所感

Dockerについて

2週間という期間があったが,1週間はDockerの勉強,残りの5日はDocker環境の構築での躓きに費やす形だった.

そのおかげで,Dockerに関する知識は相当付いたと思う.

これからDockerを勉強する人におすすめすることは,とにかく触ること.

Dockerの入門書やサイトを見ても,あまり得られるものはない.

とにかく自分が作りたい環境に近いものを作っているサイトを見つけ,Dockerfileをコピペし,

動く環境を作り,Dockerfileをコメントアウトなどして,動きを確かめる方がいいと,今回の作成を通した感じた.

一度Dockerfileを作成してしまえば,どんな環境でもすぐにコマンド一つで立ち上げることができ,

ホスト環境でやっていた開発環境と全く同じように開発できるので,本当に便利だと感じた.

VuePressについて

vuepressをインストールして,docsディレクトリにREADME.mdファイルを作成するだけで,

それっぽいドキュメントサイトが作れる.

本当に手軽で感動するので,一度は触って欲しい(2時間もあれば,誰でも完全に理解した状態)

英語なのは残念だが,とりあえずVuePressの公式サイトのガイド部分をコピペしまくれば,ある程度動きがわかる.

それでもわからない部分はVuePressの公式サイト自体のソースコードGitHubに上がっているので読む.

これである程度のことはできるようになる.

後,細かいことをしたければConfig ReferenceとDefault Theme Configを頑張って読もう.

Vue.js, Nuxt

ソースコードを見てもらうとわかるが,(root/index.html)

最初は,Vue.jsをトランスパイルせずに使っていた(初めてのこと)

そこから,Nuxtへ移行をしたのだが,とてもすんなり行き感動した.

Vue.jsのProgressive Frameworkの一部分を感じた気がした.

これはとても面白い体験で,未だにjQueryが使われているプロジェクトがあり,

それを今風に変えていきたいなら,Vue.jsをお勧めする.

jQuery→Vue.js→単一ファイルコンポーネント

の順にリファクタリングしていくのが,いいのではないだろうか.

まとめ

今回の課題は,2週間でブログシステムを作成するというものだったが,新しい知識を利用したり,

なぜか,新卒なのに開発フローの改善を提案するために,Slackの運用ルール作成したり,新開発フローを作成したり,

課題とは違うことにも,たくさんの時間を使うことになってしまったが,無事完成させることができた.

新しい知識に時間を使いすぎて,会社の人に怒られてしまったが,今回の課題はDockerfileを使う側から作る側にもなれるようになったし,

VuePressという、まだ情報が少ないものを使うこともできたし,とてもエンジニアらしい感じのことができて満足でした.

どんどん新しい知識を入れていきたいと思います.

このシステムはさくらのDockerホスティングのArukasか,さくらのVPS(いつものやつ)に近いうちにあげたいと思ってます.

質問・ご意見などありましたら,Twitterにご連絡ください.

今回のソースコードはこちらにあります.(jQueryなどを使用しているのは,僕の意志ではありません...)

(僕が自由に最新技術を追うことを許してくれる会社さんはいないのだろうか...)

もしよろしければ、Twitterのフォロー、Kyashお願いします!

twitter.com

f:id:kurowasi2525:20180616200734j:plain

github.com