Edited at

Rails / Nuxt.js / TypeScript の環境をDockerでつくる Elementの導入まで


はじめに

Gaiax Group Advent Calendar 2018の初日の記事です。

今進めているプロダクト開発でNuxt.jsを使う機会があり、環境構築をより理解するために今回Qiitaに書こうと思いました。

前提として、Ruby on Railsの環境がそこにあるとして進めていきます。


技術スタック

今回の環境構築での技術スタックは以下のようになります。

- ruby 2.5.3

- Rails 5.1.6
- node 8.1.2
- MySQL 5.7


Railsのプロジェクトを作成

では環境構築を行なっていきます。

以下のコマンドでnuxt-rails-appという名前でアプリケーションを作成します。

$ rails _5.1.6_ new nuxt-rails-app --api -d mysql

--apiと書いて上げることでAPIモードになります。

参考) Rails による API 専用アプリ


Dockerfileを作成

次にルートディレクトリ直下にDockerfileを作成します。

作成できたらDockerfileに以下のコードを追加してください。

nuxt-rails-app (ルートディレクトリ)

└── Dockerfile

FROM ruby:2.5.3-slim

RUN apt-get update -qq \
&& apt-get install -y build-essential default-libmysqlclient-dev \
&& rm -rf /var/lib/apt/lists/* \
&& gem update

WORKDIR /app
COPY Gemfile /app/
# COPY Gemfile.lock /app/

RUN bundle install -j4

EXPOSE 3000

CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]

Gemfile.lockのところをコメントアウトしている理由は、自分のPCの環境にMySQLが入っておらず、rails newした際にGemfile.lockファイルが作成されていないためです。rails newした際にGemfile.lockが作成される場合はGemfile.lockのところのコメントアウトはしなくて大丈夫です。


docker-compose.ymlを作成

次にルートディレクトリ直下にdocker-compose.ymlを作成します。

作成できたらdocker-compose.ymlに以下のコードを追加してください。

nuxt-rails-app (ルートディレクトリ)

└── docker-compose.yml

version: '2'

services:
db:
image: mysql:5.7.23
restart: always
environment:
MYSQL_ROOT_PASSWORD: nuxt-rails-app
volumes:
- ./db/mysql/volumes:/var/lib/mysql
web:
build: .
ports:
- 3000:3000
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/app
links:
- db
env_file:
- .env
tty: true
stdin_open: true


.envと.env.exampleを作成

次に.envファイルと.env.exampleファイルをルートディレクトリ直下に作成します。

作成したら、.env.exampleに以下のコードを追加します。

USER=root

PASSWORD=
HOST=db


.gitignoreを編集

次に.envファイルとdb/mysqlがコミットされないように.gitignoreファイルに以下のコードを追加します。

.env

db/mysql


Railsのデフォルト画面を表示

以下のコマンドでビルドを実行します。

$ docker-compose build

次にコンテナを作成して、起動します。

$ docker-compose up -d

上記のコマンドを実行したらlocalhost:3000にアクセスして、Railsのデフォルト画面が表示されていればうまく動作しています。

image


Dockerfileのコメントアウトを外す

DockerfileのGemfile.lockのところのコメントアウトを外します。

FROM ruby:2.5.3-slim

RUN apt-get update -qq \
&& apt-get install -y build-essential default-libmysqlclient-dev \
&& rm -rf /var/lib/apt/lists/* \
&& gem update

WORKDIR /app
COPY Gemfile /app/

# この行のコメントアウトを外す
COPY Gemfile.lock /app/

RUN bundle install -j4

EXPOSE 3000

CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]


docker-compose.ymlにfrontendコンテナの記述を追加する

次にdocker-compose.ymlにfrontendコンテナの記述を追加します。

version: '2'

services:
db:
image: mysql:5.7.23
restart: always
environment:
MYSQL_ROOT_PASSWORD: nuxt-rails-app
volumes:
- ./db/mysql/volumes:/var/lib/mysql
web:
build: .
ports:
- 3000:3000
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/app
links:
- db
env_file:
- .env
tty: true
stdin_open: true
# ここから追加
frontend:
build: ./frontend
tty: true
ports:
- 8000:3000
command: yarn dev
volumes:
- .:/app


Nuxtのプロジェクトを作成

まず以下のコマンドでvue-cliとvue/cli-initをインストールします。

$ npm install -g @vue/cli

$ yarn global add @vue/cli-init

次に以下のコマンドでNuxtのプロジェクトを作成します。

$ vue init nuxt-community/typescript-template frontend

次にfrontendディレクトリに移動してyarn installを実行します。

$ cd fronend

$ yarn install


frontendディレクトリの中にDockerfileを作成

次にfrontendディレクトリ内にDockerfileを作成します。

frontend

└── Dockerfile

FROM node:8.12-slim

WORKDIR /app/frontend

ENV PATH /app/frontend/node_modules/.bin:$PATH

RUN apt-get update -qq \
&& rm -rf /var/lib/apt/lists/*

ENV TZ Asia/Tokyo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

COPY package.json /app/frontend/package.json
COPY yarn.lock /app/frontend/yarn.lock

RUN yarn install --no-progress --registry http://registry.npmjs.org/
ENV HOST 0.0.0.0


Nuxtの画面を表示

まず、以下のコマンドを実行して、コンテナを停止させます。

$ docker-compose down

次に以下のコマンドでコンテナを起動させます。

$ docker-compose up -d

上記のコマンドを実行したら、http://localhost:8000にアクセスして以下の画面が表示されればうまく動作しています。

image

これで環境構築は終了ですが、Elementも導入してみます。


Element UIも使ってみよう

Vue.js上で高機能なUIコンポーネントが使えるライブラリ「Element」は非常に便利なので、Elementの導入もここに記載したいと思います。

参考) Element

まず、element-uiをインストールします。

$ yarn add element-ui

次にnuxt.config.jsに以下のコードを追加します。

frontend

└── nuxt.config.js

  .

.
.
// この行にelement-ui/lib/theme-chalk/index.cssを追加する
css: ["~/assets/css/main.css", "element-ui/lib/theme-chalk/index.css"],
build: {},
modules: [
"@nuxtjs/axios",
"~/modules/typescript.js"
],
// この行を追加する
plugins: ["~plugins/element-ui"],
axios: {}
}

次にfrontendディレクトリにpluginsディレクトリを作成し、作成したpluginsディレクトリにelement-ui.jsというファイルを作成します。作成したらelement-ui.jsに以下のコードを追加します。

frontend

└── plugins
└── element-ui.js

import Vue from "vue"

import ElementUI from "element-ui"
import locale from "element-ui/lib/locale/lang/ja"

Vue.use(ElementUI, { locale })

これでElementを実装できる準備が整いました。

では、Elementが使えるか試していきたいと思います。

frontend/pagesディレクトリにform.vueを作成し、form.vueに以下のコードを追加します。

frontend

└── pages
└── form.vue

<template>

<el-form ref="form" :model="form" label-width="120px">
<el-form-item label="Activity name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="Activity zone">
<el-select v-model="form.region" placeholder="please select your zone">
<el-option label="Zone one" value="shanghai"></el-option>
<el-option label="Zone two" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="Activity time">
<el-col :span="11">
<el-date-picker
type="date"
placeholder="Pick a date"
v-model="form.date1"
style="width: 100%;"
></el-date-picker>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-time-picker
type="fixed-time"
placeholder="Pick a time"
v-model="form.date2"
style="width: 100%;"
></el-time-picker>
</el-col>
</el-form-item>
<el-form-item label="Instant delivery">
<el-switch v-model="form.delivery"></el-switch>
</el-form-item>
<el-form-item label="Activity type">
<el-checkbox-group v-model="form.type">
<el-checkbox label="Online activities" name="type"></el-checkbox>
<el-checkbox label="Promotion activities" name="type"></el-checkbox>
<el-checkbox label="Offline activities" name="type"></el-checkbox>
<el-checkbox label="Simple brand exposure" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="Resources">
<el-radio-group v-model="form.resource">
<el-radio label="Sponsor"></el-radio>
<el-radio label="Venue"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="Activity form">
<el-input type="textarea" v-model="form.desc"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">Create</el-button>
<el-button>Cancel</el-button>
</el-form-item>
</el-form>
</template>

<script>
export default {
data() {
return {
form: {
name: "",
region: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: "",
desc: ""
}
};
},
methods: {
onSubmit() {
console.log("submit!");
}
}
};
</script>

上記のコードはElementの公式ドキュメントのこちらをコピーしただけです。

https://element.eleme.io/#/en-US/component/form

コードを追加できたら、以下のコマンドを実行してコンテナの再起動を行います。

$ docker-compose down

$ docker-compose up -d

上記のコマンドを実行したら、http://localhost:8000/formにアクセスします。すると下記のようにフォームのUIが表示されます。

image

このようにElementを使えば簡単にUIを作ることができるので非常に便利です。

以上でRails・Nuxt.js の環境をDockerでつくりElementの導入まで行いました。

読んでくださってありがとうございました。