何をしたいか
複数メンバーでVuetifyを使って軽く開発をすることになったのだが、各メンバーのスキルにバラツキがあるため(殆どプログラミング経験ないメンバー有)、出来るだけ事前準備無しで環境を作ろうと思ったのがきっかけである。
全員VScodeを使うが、ソースコードを置く場所がWindowsだったりMacだったり、リモートのCentOSマシンだったりとバラバラ。
それぞれの環境でnpm installしてnode_modulesのフォルダが出来て、となると結構面倒なので、git cloneしてdocker-composeすれば全て用意されるようにしたかった
今回の記事では以下の事を実現する
- コンテナ上でnpm installをしてnpm run buildも行うが、ソースコードはホスト上に置いておきたい
- node_modulesはコンテナ、ソースコードはホスト上、出来上がったdistもホスト上としたい
- Dockerfileにコマンドを書くのではなく、package.jsonからまとめてインストールしたい
- いちいちnpm run buildを実行したくないので
vue-cli-service build --watch
として自動ビルドしたい - FlaskのAPIサーバを使うのでNGINXのリバースプロキシも必要なため、distをNGINXに見せる
Git
#フォルダ構成
.
|-- app
| |-- Dockerfile
| `-- src
|-- docker-compose.yml
|-- nginx_web
| |-- Dockerfile
| `-- nginx_conf
`-- vuetify
|-- Dockerfile
|-- README.md
|-- babel.config.js
|-- dist
|-- node_modules
|-- package-lock.json
|-- package.json
|-- public
|-- src
`-- vue.config.js
Docker Compose
NGINX,Flask,Vuetifyビルド用ということで3つコンテナが立つことになる
version: '3'
services:
nginx_web:
build:
context: ./nginx_web
dockerfile: Dockerfile
container_name: nginx_web
ports:
- 80:80
volumes:
- ./vuetify:/usr/share/nginx/html
vuetify:
build:
context: ./vuetify
dockerfile: Dockerfile
container_name: vuetify
ports:
- 1234:8080
volumes:
- ./vuetify:/app
- /app/node_modules
stdin_open: true
tty: true
app:
build:
context: ./app
dockerfile: Dockerfile
container_name: app
ports:
- 3031:3031
volumes:
- ./app/src:/src
nginx_webとapp(flask)コンテナの設定についてはこちらの記事を参照
jwilder nginx-proxy + letsencrypt-nginx-proxy-companion + Flask + uwsgiでHTTPS対応のWebサービスを作り、更にQualysでA+を取る
nginx_webの設定はVuetifyのbuildに対応するため少し変更してあるので、後ほど説明する
vuetifyの部分のポイントはvolumes
の/app/node_modules
コンテナ上にnode_modulesを展開するため、コンテナ上の/app/node_modulesはvolumeとして別途確保している。
Dockerfile
使うモジュールが増えた時にnpm install <module>
を書き足すのが嫌なので、package.jsonからnpm install
で片づけたい。
FROM node:alpine
WORKDIR /app
COPY ./package*.json ./
RUN apk update
RUN npm install -g npm
RUN npm install
CMD ["./node_modules/.bin/vue-cli-service", "build", "--watch"]
package.jsonには今回利用するvue,vuetify,axiosが記載されている。
PC上で一回npm installして自動で作成されたpackage.jsonをコピーして利用している
CMD
にある--watch
は変更ファイルを見張って自動でビルドしてくれる便利機能
ここで書かずにpackage.jsonを以下のように書いて、CMD ["npm","run","build"]
としても良い
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build --watch",
"lint": "vue-cli-service lint"
},
NGINX設定
index.htmlが./vuetify/dist
に出力されるのでNGINXのデフォルトのフォワード先をここにする必要がある
それが以下の記述
server{
listen 80;
server_name nginx;
location / {
root /usr/share/nginx/html/dist;
index index.html index.htm;
}
docker-compose.ymlで
volumes:
- ./vuetify:/usr/share/nginx/html
としているので、http://localhost
でアクセスが来たら./vuetify/dist/index.html
が読み込まれる
Build
docker-compose up --build -d
とすればOK
一回目はvuetifyのビルドに数十秒かかるのでコンテナが上がってもしばらく待とう。さもなくば404が表示される
うまくいけば以下のように表示される
#Flaskとの連携
Read Data from Flask
という部分がVuetifyのデフォルトページに追加した部分である
ソースコードはこんな感じ
from flask import Flask, jsonify, request, make_response,send_from_directory
import requests
import json
app = Flask('test')
@app.route('/api/v1/get/',methods=['GET'])
def get():
return "Read Data from Flask",200
ただ文字を返しているだけのシンプルなAPIとしている
VueからのAPI呼び出し
Vueから先ほどの/api/v1/get
を呼び出しているのがこの部分
vuetifyデフォルトのHelloWorld.vueに以下の部分を追加している
<template>
...省略
<v-col cols="12" class="mb-4">
<h1 class="display-2 font-weight-bold mb-3">
{{flask_message}}
</h1>
</v-col>
...省略
<script>
import axios from "axios"
export default {
name: 'HelloWorld',
created: function() {
axios.get('/api/v1/get')
.then(response => {
this.flask_message = response.data
})
},
data: () => ({
flask_message: '',
...省略
結果
npmをインストールしていないWindows/Mac,Ubuntuなどで問題なく作動した。
vueファイルを変更してもビルドは非常に速い(1秒以下)
これで快適に開発が出来るようになった。