[Nuxt.js + Rails + PostgreSQL + Docker] でアプリ作成

開発環境
>ruby 2.7.2
Rails 6.0.3.7
node v16.1.0
npm 7.11.2

ディレクトリを作成,分ける

```
mkdir nuxt_rails
cd nuxt_rails
mkdir api 
mkdir front
```

```ruby:nuxt_rails
/
|--front/
| 
|--api/

```

docker ファイル作成 / api front 両方に作成

```
touch api/Dockerfile
```

```Dockerfile:api側

FROM ruby:2.7.2

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

RUN mkdir /app
ENV APP_ROOT /app
WORKDIR $APP_ROOT

ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock

RUN bundle install
COPY . /app
```

rm -rf /var/lib/apt/lists/*はaptのキャッシュを削除しています。これはDockerのイメージファイルサイズを軽量化するためです。

- FROM命令で、元となるimageを指定(node)
- ENV命令で、環境変数を指定
- WORKDIR命令で、/app内へ移動
- RUN命令で、packageの更新
- COPY命令で、ホストマシンのpackage.jsonとpackage-lock.jsonをコンテナ内にコピー
- RUN命令で、コンテナ内で、npm installを実行し、moduleインストール
- COPY命令で、ホストマシンのファイルをすべてコンテナにコピー
- ENV HOSTでhostを指定
- EXPOSEで公開するport番号を指定しています

 Gemfile作成

```
touch api/Gemfile
touch api/Gemfile.lock

# api/Gemfileに記入

source 'https://rubygems.org'
gem 'rails', '~> 6.0.3.7'
```

docker-compose.yml作成

```
touch docker-compose.yml
```

```yml
version: '3'

services:
  app:
    build: ./api
    command: /bin/sh -c "bundle install && bundle exec puma -C config/puma.rb"
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    ports:
      - '3000:3000'
    depends_on:
      - db
    volumes:
      - .:/api:delegated
      - ./api:/app
      - bundle:/usr/local/bundle
    tty: true
    stdin_open: true
  db:
    stdin_open: true
    tty: true
    restart: always
    image: mysql:5.7.32
    ports:
      -  '3306:3306'
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_USER: root
      MYSQL_DATABASE: root
      TZ: Asia/Tokyo
    volumes:
      - mysql_data:/var/lib/mysql/
  front:
    build: ./front
    volumes:
      - ./front:/app
    ports:
      - '8080:8080'
    tty: true
    stdin_open: true
    command: npm run serve

volumes:
  mysql-data:
  bundle:
```
- buildで【.】を指定することで、同一ディレクトリのDockerfileを元にcontainerを作成します
- commandでコンテナが立ち上がったタイミングで、npm run dev命令を実行するように指定
- portsでホストマシンの3000番portとコンテナの3000番portを照合します
- depends_on によって起動順は制御することができますが稼働順は制御することができません
- volumesで、ホストマシンのカレントディレクトリをコンテナの/app似マウント
- tty trueで対話モードで実行します
- stdin_open コンテナの標準入力をオープンしたままにする
- working_dirでコマンドを実行するディレクトリを指定
- restart コンテナがすでに存在していた際の挙動を指定する
- environment 設定する環境変数とその値を指定する

```ruby:nuxt_rails
/
|--front/
|    |--Dockerfile
|--back/
|    |--Dockerfile
|    |--Gemfile
|    |--Gemfile.lock
|--docker-compose.yml

```

Railsをapiモードで立ち上げる

```
docker-compose run app rails new . --force --database=postgresql --api --skip-bundle
```

rails newの引数について

--force：Gemfileを強制的に上書き更新する

--database:使用するデータベースをpostgresqlにする

--api：APIモードでプロジェクトを作成。APIモードではUIに関係するファイルが省略されます。

--skip-bundle：bundle installを省略します。次のdockerイメージのビルドでbundle installをするためです。

dockerイメージ更新
Gemfileが更新されたので、buildしてdocker imageを更新します。

```
docker-compose build
docker-compose run app bundle
```

database.ymlの設定

```yml
default: &default
  adapter: postgresql
  encoding: unicode
  username: pguser
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  password: pgpass
  host: db

development:
  <<: *default
  database: app_development

test:
  <<: *default
  database: app_test

production:
  <<: *default
  database: app_production
  username: app
  password: <%= ENV['APP_DATABASE_PASSWORD'] %>
```

```
docker-compose run app rails db:create
```
vue-cliでVueプロジェクトを作成
コンテナ内に入り、vue-cliを使ってVueプロジェクトの作成を対話的にします。

nuxtjsのインストール

```
cd front
npx create-nuxt-app
```

```

npx create-nuxt-app

create-nuxt-app v3.6.0
✨  Generating Nuxt.js project in .
? Project name: front
? Programming language: JavaScript
? Package manager: Npm
? UI framework: Vuetify.js
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Testing framework: Jest
? Rendering mode: Single Page App
? Deployment target: Server (Node.js hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Continuous integration: GitHub Actions (GitHub only)
? What is your GitHub username? 
? Version control system: circleci

```

frontのDockerfile作成

```
touch front/Dockerfile

front/Dockerfile
```

front側

```Dockerfile
FROM node:12.18.3-alpine

ENV APP_HOME /app
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME

RUN apk update && npm install -g @vue/cli
```

```
docker-compose build
```
nuxt.config.jsに下記を追加

```javascript
export default {
  // Disable server-side rendering: https://go.nuxtjs.dev/ssr-mode
  ssr: false,

  server: {
    port: 8080,
    host: '0.0.0.0',
  },
```

動作確認


```
$ npm run dev
```
ソースマップを作成し、js/cssを縮小しないため、デバッグとエラーの発見が容易になります

コンテナを立ち上げる

```
$ docker-compose up
```

docker-compose up -d: バックグラウンドでプロセスを実行する


5-1. Rails

http://localhost:3000
にアクセスし以下のページが表示されることを確認

![localhost 3000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993960/5b179ffd-ae57-272e-f2b2-17264664f6ea.png)


5-2. nuxt


http://localhost:8080
にアクセスし以下のページが表示されることを確認

![localhost 8080.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993960/a659adc9-11b5-a611-bbac-8542f257333b.png)