Rails
docker
vue.js
nuxt.js
ElementUI

Rails / Nuxt.js の環境を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の導入まで行いました。
読んでくださってありがとうございました。