Docker for WindowsでVue CLI 3 + Bulma環境構築

今さら感はありますが、最近やっとDockerを本格的に使うようになってきました。
これまでの個人的な開発は、Vagrantで仮想マシン自体を生成し使用していたり、そもそもサーバサイドが必要ないSPAであればVue.jsでまかなえるので、Windows自体にNode.jsをインストールしてました。
しかし、Pythonの環境ほしくてDocker for Windowsを使ってみると、想像以上に良くなっていたので開発環境はDockerに全部移行しようかと考えてます。

まずは、所得税・住民税・事業税・国民健康保険計算シミュレーション適用可能な控除を簡単判定の環境用に、Vue CLI 3とBulma用のコンテナを作成します。

目的

  • Docker for Windows上にコンテナ作成
  • コンテナ内にNode等の必須パッケージをまとめ、Windows(ホスト)側はなるべく追加のインストールはしない
  • なるべくコンテナ内に入ることはせず、Windows側の操作のみでVueプロジェクトを開発

今までは使い勝手を考えて、Windows側にNode.jsもインストールしてましたがもやもやしてました。
(最初はVagrant内で完結させてましたけど、途中からVagrantを上げるの自体おっくうに。。。)
全部コンテナに押し込めてWindowsはなるべくクリーンに!
そして、せっかくVue UIというGUI管理ツールがVue CLI 3から備わってるので、フル活用すれば意外といけるのでは?と思ってます。

環境

  • Windows 10 Pro
  • Docker for Windows インストール済み
  • 作業フォルダは「c:\develop\docker\vue」とします

※ Docker for WindowsはHyper-Vが必須なので、WindowsはProじゃないとだめです。
Docker for Windowsが未インストールの方は、以下記事をご参考ください。

コンテナ作成(失敗編)

コンテナは容量が最小限と噂のalpineを使ってみましたが失敗しました。
どうもVue UIと相性悪いようです。興味ない方は読み飛ばしてください。

node:alpineベースイメージで作成するコンテナのDockefile作成

Nodeのバージョンは2019年2月7日時点で最新の11.9にしました。
Dockefile

FROM node:11.9-alpine
RUN npm install -g @vue/cli
EXPOSE 8080
EXPOSE 8000

CMD vue ui

※ Dockerfileの中のコマンドに関しては、ヘルプ等を見てください。ここでは説明しません。

ビルド

それでは早速作業ディレクトリへ移動しビルドします。

> cd c:\develop\docker\vue
> docker build -t node:vue3 .

なんかエラーが発生しました。どうもダウンロード中にタイムアウトしているようです。

Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM node:11.9-alpine
ERROR: Service 'xxxx' failed to build: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

何回繰り返しても同じ結果なので、ググってみるとDNSを固定にするといいみたいです。
Docke for Windowsの「Settings」を開きNetworkメニューからDNSの設定を変更します。
デフォルトは、AutomaticになっているはずなのでFixedに変更しGoogoleのDNSにします。(すでに入力済みなのでチェック変えるだけ)

docker dns

再度ビルド実行すると成功!

> docker build -t node:vue3 .

Sending build context to Docker daemon  2.048kB
Step 1/5 : FROM node:11.9-alpine
 ---> ebbf98230a82
Step 2/5 : RUN npm install -g @vue/cli
 ---> Running in fd486dec41fd
npm WARN deprecated cross-spawn-async@2.2.5: cross-spawn no longer requires a build toolchain, use it instead
/usr/local/bin/vue -> /usr/local/lib/node_modules/@vue/cli/bin/vue.js

> protobufjs@6.8.8 postinstall /usr/local/lib/node_modules/@vue/cli/node_modules/protobufjs
> node scripts/postinstall

> nodemon@1.18.9 postinstall /usr/local/lib/node_modules/@vue/cli/node_modules/nodemon
> node bin/postinstall || exit 0

Love nodemon? You can now support the project via the open collective:
 > https://opencollective.com/nodemon/donate

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.7 (node_modules/@vue/cli/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.7: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})

+ @vue/cli@3.4.0
added 667 packages from 501 contributors in 49.13s
Removing intermediate container fd486dec41fd
 ---> 23a85072db89
Step 3/5 : EXPOSE 8080
 ---> Using cache
 ---> 41e1da929db7
Step 4/5 : EXPOSE 8000
 ---> Using cache
 ---> 2a9b7aca082d
Step 5/5 : CMD vue ui
 ---> Using cache
 ---> 8bd0796f15f3
Successfully built 8bd0796f15f3
Successfully tagged node:vue3
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.

vue cliのインストール時や最後にワーニングでてますがメッセージから問題ないようなのでいったん無視しイメージが作成されたか確認してみます。

> docekr images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
node                vue3                67ac3ec3350c        22 seconds ago      162MB
node                11.9-alpine         ebbf98230a82        6 days ago          73.7MB

できてますね。
それでは起動してみます。

> docker run -d --rm --name vue3_1 -v c:/develop/docker/vue:/app -p 8000:8000 -p 8080:8080 node:vue3

起動したコンテナ確認してみます。

> docker ps 

CONTAINER ID        IMAGE               COMMAND                 CREATED             STATUS              PORTS                                            NAMES
3f1ab1c905c5        node:vue3           "/bin/sh -c 'vue ui'"   3 seconds ago       Up 2 seconds        0.0.0.0:8000->8000/tcp, 0.0.0.0:8080->8080/tcp   vue3_1

起動してますね。それではvue-uiが立ち上がってるかブラウザで確認します。

not access

ダメでした。 docker側のログを見てみます

> docker logs vue3_1
🚀  Starting GUI...
🌠  Ready on http://localhost:8000

Vue UIは立ち上がっているようですが、localhostになってますね。これではつながらないのでdocker runコマンドでコマンド部の引数で調整します。

# コンテナ停止と削除
> docker stop vue3_1 && docker rm vue3_1
# コンテナ起動
> docker run -d --rm --name vue3_1 -v c:/develop/docker/vue:/app -p 8000:8000 -p 8080:8080 node:vue3 vue ui -H 0.0.0.0

繋がりました!

vue ui 起動画面

※ Dockerfileを修正してビルドしなおし、コマンドの引数を付けないでも起動するよう修正しておくと楽です。CMDの使い方間違ってる気がするけど。。もっと勉強が必要。

Dockefile

~

CMD vue ui -H 0.0.0.0

Vue UIでプロジェクト作成と起動

※ こちらは失敗編です。興味ない方は読み飛ばしてください。

それでは、マウントしたフォルダ以下にプロジェクト作成していきます。
画面下の「+ここに新しいプロジェクトを作成する」をクリックします。

vue create

プロジェクト名は「bulma-project」で。
パッケージマネージャーは、npmを選択します。

プロジェクト名

ここからは、vue createコマンドで実行した場合に聞かれるプリセットの選択が続きます。
デフォルトじゃ足りないので「手動」を選択。

プリセット選択1

必要なパッケージを取捨選択します。Bulmaを導入しsassでカスタマイズするのでCSS Pre-processorsは選択しておきます。

プリセット選択2

選択したパッケージについての設定が続きます。Sass/SCSS(with nod-sass)を選択。
node-darkというのも選択できますが、よくわかりません。。。今度調べてみるか。

CSSプロセッサ選択

最後に今まで選択したプリセットを保存するか聞かれます。どちらでもいいです。
プロセット保存

インストールが始まると以下のような画面に。時間かかります。
処理中

終わったと思ったら、なぜかプロジェクト作成の最後の画面に戻りました。。

create failed

これは嫌な予感。。
ディレクトリを見ても、node_modules とpackage.jsonしかありません。失敗したようです。

c:\develop\docker\vue\bulma-project のディレクトリ

2019/02/08  23:28    <DIR>          .
2019/02/08  23:28    <DIR>          ..
2019/02/08  23:30    <DIR>          node_modules
2019/02/08  23:27               210 package.json

とりあえずログ見てみます。

> docker logs vue3_1

> yorkie@2.0.0 install /app/bulma-project/node_modules/yorkie
> node bin/install.js

fs.js:120
    throw err;
    ^

Error: EINVAL: invalid argument, open '/app/bulma-project/node_modules/yorkie/package.json'
    at Object.openSync (fs.js:449:3)
    at Object.readFileSync (fs.js:349:35)
    at Object.Module._extensions..json (internal/modules/cjs/loader.js:751:22)
    at Module.load (internal/modules/cjs/loader.js:626:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:566:12)
    at Function.Module._load (internal/modules/cjs/loader.js:558:3)
    at Module.require (internal/modules/cjs/loader.js:663:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at Object.<anonymous> (/app/bulma-project/node_modules/yorkie/src/utils/get-hook-script.js:5:13)
    at Module._compile (internal/modules/cjs/loader.js:734:30)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! yorkie@2.0.0 install: `node bin/install.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the yorkie@2.0.0 install script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2019-02-08T14_30_25_636Z-debug.log
command failed: npm install --loglevel error --registry=https://registry.npm.taobao.org --disturl=https://npm.taobao.org/dist

はい、エラーがでて見事に失敗してます。結局このエラーの原因および解決方法はわからず。
なんとなくですが、ホストがWindowsのフォルダをマウントしておりそこにインストールするとエラーになる模様。相変わらず相性悪い。

色々模索していると、パッケージマネージャーを「npm」ではなく「yarn」にすればいけました。

yarn

タスクを実行して無事にvueのWelcome画面が表示されたので出来たと思ったのですが、なんとタスクを切るとコンテナまで落ちる現象が!

task-kill

以上が失敗編です。タスク停止するたびにコンテナが落ちてしまうため、使い物になりませんでした。
私の力では原因究明できなかったので、だれか教えてください。。

コンテナ作成(成功編)

ここからやっと成功編です。長かった。
基本的な手順は同じで、コンテナのもととなるイメージは「node:latest」を使う。それだけ!

失敗編が長くなったので、サクッといきます!

node:latestベースイメージで作成するコンテナのDockefile作成

Dockefile

FROM node:latest
RUN npm install -g @vue/cli
EXPOSE 8080
EXPOSE 8000

CMD vue ui

ビルドとコンテナ起動

# ビルド
> docker build -t node:vue3 .
# コンテナ起動
> docker run -d --rm --name vue3_1 -v c:/develop/docker/vue:/app -p 8000:8000 -p 8080:8080 node:vue3

Vue UIでプロジェクト作成と起動

手順は失敗編と同じで、注意点はパッケージマネージャーに「yarn」を使うところだけ。
画面イメージは失敗編見てください!

出来上がったら自動的にプロジェクトダッシュボード画面が表示されます。
project-dashbord

画面左側メニューの「タスク」を選び「タスクの実行」ボタンを押すとビルドが終了するので「アプリを開く」をクリック
task

無事にvueの画面が開きます。
welcome-vue

タスク画面から「タスクの停止」ボタンを押してもタスクだけ止まります。コンテナ落ちない!すばらしい!

Bulmaのインストール

それではBulmaをインストールします。画面からさっくりとできます。

メニューの「依存」を選択しプロジェクト依存画面の右上の「依存をインストール」をクリック。
依存インストール

検索部にbulmaと入力するとbulma関係のパッケージが抽出されるので、「bulma 0.7.4」を選択し、右下の「bulmaをインストール」をクリックでインストール完了します。

Bulmaインストール

Bulmaの設定は、別記事にまとめてます。こちらを参考にSassでのカスタマイズができるように設定。

Bulmaの導入・設定が終わればWelcom画面は以下のような画面になるはずです。
vue-bulma

HMR(Hot Module Reload)の設定

Windows + Vagrantの環境と同じで、ホストがWindowsの場合は、HMR(Hot module reload)が動作しません。
解決方法は同じなので、ポーリングの設定を追加すれば問題ありません。

vue.config.js

module.exports = {
  devServer: {
    watchOptions: {
      poll: 300
    }
  },
  css: {
    loaderOptions: {
      sass: {
        data: `@import "@/variables.sass";`
      }
    }
  }
}

css~はsass用の設定値です。

これで無事に開発環境ができました。一回作ってしまえば起動は一瞬なので使いたいときにサクッと立ち上げれます。
これでWindowsにNode.jsをインストールする必要性は、今のところなくなりました。めでたしめでたし。

最後に

この最終系にたどりつくまでに結構時間かかってしまいました。おかげさまでDockerの理解も進みました。
今回はDockerfileのみでの環境作成でしたが、実際はdocker-composeでの管理がとても便利なので、1コンテナでもdocker-composeを作るようにしてます。もっと早く使ってみとけばよかったな、Dokcer。