目的
6月あたりから仕事でRails&Vueの開発をしているんですが参加した時点ではコーディングできる状態になっていて
自分ではプロジェクト作成や開発環境構築などを全くしなかったのでその辺の理解を深めるために
年末年始を使って自力で構築してみました
最終的なゴール
- Docker上で、Rails&Vue(webpackで単一ファイルコンポーネント)のSPAの開発環境を構築 ←今回やる
- swaggerを使ってAPI定義してバックエンドとフロントエンドを円滑に開発
- リポジトリへpush時にCIで自動テストしてAWS(Elastic Beanstalk)へデプロイされるようにする
今回のゴール
- Docker上でバックエンド(Rails)とフロントエンド(Vue.js)の開発ができる状態にする
- ローカルでの開発だけでなくデプロイして公開できる状態にする
- webpackでビルドしたものをRailsから配信できる状態
技術スタック
・Docker
・Rails
・Vue.js
・Webpack(Webpackerもいずれ試す)
Railsプロジェクト作成
必要なディレクトリとファイル作成
ディレクトリを作ってその中に
- Dockerfile
- docker-compose.yml
- Gemfile
を作る
rails_vue_spa/
├ Dockerfile
├ docker-compose.yml
└ Gemfile
FROM ruby:2.5.1
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - &&\
apt-get update -qq &&\
apt-get install -y nodejs
ENV TZ=Asia/Tokyo
COPY Gemfile .
RUN bundle install
WORKDIR /usr/src/app
Ruby環境のイメージをビルドするためのDockerfile
version: '3'
volumes:
bundle:
services:
app:
build: .
ports:
- 3000:3000
volumes:
- bundle:/usr/local/bundle
- .:/usr/src/app:delegated
stdin_open: true
tty: true
command: /bin/sh
そのうちDBのコンテナと繋げる&操作性がdocker-composeの方が好きなのでdocker-compose.ymlを用意
source 'https://rubygems.org'
gem 'rails', '~> 5.2.2'
とりあえずrails
だけ
Docker立ち上げてRailsプロジェクト作る
$ docker-compose build
$ docker-compose up -d
$ docker-compose exec app sh
# rails new .
exist
create README.md
create Rakefile
create .ruby-version
create config.ru
create .gitignore
conflict Gemfile
Overwrite /usr/src/app/Gemfile? (enter "h" for help) [Ynaqdhm]
y
でエンター
# rails s -b 0.0.0.0 -p 3000
で http://localhost:3000 でrailsサンプルページが表示されるか確認
# ^C
# exit
Ctrl+C
でrailsサーバ止めてDocker上のコンソール終了
$ docker-compose down
一度Docker止める
Dockerの設定修正
FROM ruby:2.5.1
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - &&\
apt-get update -qq &&\
apt-get install -y nodejs
ENV TZ=Asia/Tokyo
COPY Gemfile .
COPY Gemfile.lock .
RUN bundle install
WORKDIR /usr/src/app
イメージビルド時にlockファイルからgemがインストールされるようにDockerfile
を修正
version: '3'
volumes:
bundle:
services:
app:
build: .
ports:
- 3000:3000
volumes:
- bundle:/usr/local/bundle
- .:/usr/src/app:delegated
stdin_open: true
tty: true
command: /bin/sh -c "bundle install; rm /usr/src/app/tmp/pids/server.pid; rails s -b 0.0.0.0 -p 3000"
コンテナ起動時にもlockファイルからgemがインストールされ、
railsサーバが起動するようにdocker-compose.yml
修正
rm /usr/src/app/tmp/pids/server.pid;
はコンテナ止める時にpidファイルが残って再度サーバ立ち上げようとした時にエラーになることがあるため
$ docker-compose build --no-cache
$ docker-compose up -d
で http://localhost:3000 にアクセスしてサンプルページが表示されればok
Railsプロジェクトの中にVueの開発環境構築
frontend/
配下にVueプロジェクト作成
$ docker-compose exec app sh
Dockerの中に入って
# pwd
/usr/src/app
# mkdir frontend
# cd frontend
# npm install -g vue-cli
# vue init webpack
? Generate project in current directory? (Y/n) y
? Project name (frontend)
? Project description A Vue.js project
? Author
❯ Runtime + Compiler: recommended for most users
Runtime-only: about 6KB lighter min+gzip, but templates (or any Vue-specific HTML) are ONLY allowed in .vue files - render functions are required elsewhere
? Install vue-router? (Y/n) y
? Use ESLint to lint your code? (Y/n) y
? Pick an ESLint preset
❯ Standard (https://github.com/standard/standard)
Airbnb (https://github.com/airbnb/javascript)
none (configure it yourself)
? Set up unit tests (Y/n) y
? Pick a test runner (Use arrow keys)
❯ Jest
Karma and Mocha
none (configure it yourself)
? Setup e2e tests with Nightwatch? (Y/n) y
? Should we run `npm install` for you after the project has been created? (recommended) (Use arrow keys)
❯ Yes, use NPM
Yes, use Yarn
No, I will handle that myself
- Railsプロジェクト直下に
frontend
ディレクトリ作成 - vue-cliをインストール
- vueプロジェクト作成(色々選択肢出るけど基本ずっとそのままエンターでok)
Dockerの設定を修正
FROM ruby:2.5.1
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - &&\
apt-get update -qq &&\
apt-get install -y nodejs
ENV TZ=Asia/Tokyo
WORKDIR /usr/src/app
COPY Gemfile .
COPY Gemfile.lock .
RUN bundle install
RUN mkdir frontend
COPY frontend/package.json frontend/.
COPY frontend/package-lock.json frontend/.
RUN cd frontend && npm install
- イメージビルド時に
frontend
直下にnode_modules
をインストールするように修正
version: '3'
volumes:
bundle:
services:
app:
build: .
ports:
- 3000:3000
- 8080:8080
volumes:
- bundle:/usr/local/bundle
- .:/usr/src/app:delegated
- /usr/src/app/frontend/node_modules
stdin_open: true
tty: true
command: /bin/sh -c "bundle install; rm /usr/src/app/tmp/pids/server.pid; rails s -b 0.0.0.0 -p 3000"
- webpack-dev-server用に8080ポート開ける
- ボリュームマウント時に
node_modules
が消えないようにボリュームトリックを使う(※参考)
$ docker-compose down
$ docker-compose build --no-cache
$ docker-compose up -d
Dockerイメージビルドからし直して立ち上げる
webpack-dev-serverの設定修正
host: 'localhost', // can be overwritten by process.env.HOST
を
host: '0.0.0.0', // can be overwritten by process.env.HOST
に修正
webpack-dev-server起動して確認
$ docker-compose exec app sh
でDockerに入って
# cd frontend
# npm run dev
webpack-dev-server起動して
http://localhost:8080/#/ にアクセスにサンプルページが表示されればok
Ctrl+C
で終了
Vueプロジェクトをビルドしてみる
# pwd
/usr/src/app/frontend
# npm run build
でフロントエンドをビルドするとfrontend/dist
の直下に
ビルドしたcssやjsとそれらを読み込んでいるindex.htmlが作成される
rails_vue_spa/
└ frontend/
└ dist/
├ index.html
└ static/
├ css/
│ ├ app.30790115300ab27614ce176899523b62.css
│ └ app.30790115300ab27614ce176899523b62.css.map
└ js/
├ app.f79767c5ed5e2af21cfb.js
├ app.f79767c5ed5e2af21cfb.js.map
├ manifest.2ae2e69a05c33dfc65f8.js
├ manifest.2ae2e69a05c33dfc65f8.js.map
├ vendor.42fc6c515ccdfe89bd76.js
└ vendor.42fc6c515ccdfe89bd76.js.map
そのままだとビルドしてできたものにハッシュがついてて扱いづらいのでハッシュがつかないようにする
Vueプロジェクトのビルドの設定変更
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
.
.
.
filename: utils.assetsPath('css/[name].[contenthash].css'),
を
filename: utils.assetsPath('js/[name].js'),
chunkFilename: utils.assetsPath('js/[id].js')
.
.
.
filename: utils.assetsPath('css/[name].css'),
へ修正して
# npm run build
ビルドしなおすと
rails_vue_spa/
└ frontend/
└ dist/
├ index.html
└ static/
├ css/
│ ├ app.css
│ └ app.css.map
└ js/
├ app.js
├ app.js.map
├ manifest.js
├ manifest.js.map
├ vendor.js
└ vendor.js.map
となる
ビルドしたフロントエンドのファイルをRailsサーバから配信されるようにする
Railsのルーティングとコントローラ準備
root to: 'index#index'
class IndexController < ApplicationController
def index; end
end
Railsのviews作成
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width,initial-scale=1">
<title>frontend</title>
<link href=/static/css/app.css rel=stylesheet>
</head>
<body>
<div id=app></div>
<script type=text/javascript src=/static/js/manifest.js></script>
<script type=text/javascript src=/static/js/vendor.js></script>
<script type=text/javascript src=/static/js/app.js></script>
</body>
</html>
を参考にcssとjs読み込み部分をassets以下を読み込むように修正して以下のerbを作る
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width,initial-scale=1">
<title>frontend</title>
<%= stylesheet_link_tag 'application', media: 'all' %>
</head>
<body>
<div id=app></div>
<%= javascript_include_tag 'application' %>
</body>
</html>
このままだとまだ読み込まれないので
frontend/dist/static/css/*
をapp/assets/stylesheets/frontend/
配下へ、
frontend/dist/static/js/*
をapp/assets/javascripts/frontend/
配下へ移動する
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require_tree .
を
//= require frontend/manifest
//= require frontend/vendor
//= require_tree .
へ変更
//= require_tree .
だけで置いてあるjs全部読み込むが
manifest
とvendor
を先に読み込まないとエラーになるので上記のようにする必要がある
これでvueでビルドしたものがrailsから配信されるようになるので
http://localhost:3000 にアクセスするとvueのサンプルページが表示されるようになる
画像について
ロゴのpngとかはbase64にエンコードされた状態になるためビルドした時に画像は出力されないが
ぐるぐるするアニメーションのgifはエンコードされずdist/static/img/
配下に出力される(なんでだろう?)
試しにfrontend/src/asstes/loader.gif
を置いて
<img src="./assets/logo.png">
を
<img src="./assets/loader.gif">
にしてビルドするとdist/static/img/loader.78f8cb8.gif
も生成されるようになる
が、
画像のパスstatic/img/loader.78f8cb8.gif
がapp.js
の中に書かれてしまうため
frontend/dist/static/img/
配下をapp/assets/images/
ではなくpublic/static/img/
配下に置く
フロントエンドのビルドが楽になるように
上記のcss,js,imgの移動を含めたビルドの流れをスクリプトにまとめる
#!/bin/bash
cd /usr/src/app/frontend
npm install
npm run build
cp -a /usr/src/app/frontend/dist/static/js/. /usr/src/app/app/assets/javascripts/frontend
cp -a /usr/src/app/frontend/dist/static/css/. /usr/src/app/app/assets/stylesheets/frontend
if [ -d /usr/src/app/frontend/dist/static/img/ ] ;then
# ディレクトリないとcpでエラーになるからなければ作る
if [ ! -d /usr/src/app/public/static/img ] ;then
mkdir -p /usr/src/app/public/static/img
fi
cp -a /usr/src/app/frontend/dist/static/img/. /usr/src/app/public/static/img/
fi
ここまで準備すると、
docker-compose exec app scripts/build-frontend.sh
とか
$ docker-compose exec app sh
# scripts/build-frontend.sh
ってするだけでフロントエンドがビルドされて最新状態のものが
http://localhost:3000
で見れるようになる
このスクリプトは後々のCIでのビルド&デプロイでも活用する
〆
ってことで今回のゴール
- Docker上でバックエンド(Rails)とフロントエンド(Vue.js)の開発ができる状態にする
- ローカルでの開発だけでなくデプロイして公開できる状態にする
- → webpackでビルドしたものをRailsから配信する
までたどり着きました
次回は
swaggerを使ってAPI定義してバックエンドとフロントエンドを円滑に開発
次次回
リポジトリへのpush時にCIで自動テストしてAWS(Elastic Beanstalk)へデプロイされるようにする
をやってみたいと思います