Ruby on Rails+Nuxt.jsの環境をDockerで作成するための手順メモ。
環境構築とAPI実装&呼び出し方法について。
開発環境
- MacOS Ventura(バージョン13.5)
- Docker Compose version v2.20.2-desktop.1
- Ruby 3.2.0
- Rails 7.0.7
- PostgreSQL 12.16
- Node 16.15.1
- Nuxt.js 2.15.8
ディレクトリとファイルを作成
以下のディレクトリ構成でファイルを作成します。
MyApp
├─ web
│ ├─ Dockerfile
│ ├─ Gemfile
│ └─ Gemfile.lock
├─ front
│ └─ Dockerfile
├─ docker-compose.yml
└─ .git
# -----------------------------------
# Ruby on Rails環境構築用のDockerfile
# -----------------------------------
# ベースにするイメージ
FROM ruby:3.2.0
# RailsのインストールやDBへの接続に必要なパッケージをインストール(今回はPostgreSQLを使用する)
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs postgresql-client
# コンテナ内にアプリ用のディレクトリを作成
RUN mkdir /MyApp
# 作成したディレクトリを作業用ディレクトリとして設定
WORKDIR /MyApp
# ローカルのGemfileとGemfile.lockをコンテナに配置
ADD Gemfile /MyApp/Gemfile
ADD Gemfile.lock /MyApp/Gemfile.lock
# コンテナ内にコピーしたGemfileのbundle install
RUN bundle install
# ローカルのファイルをコンテナに配置
COPY . /MyApp
source 'https://rubygems.org'
gem 'rails', '~> 7.0.7', '>= 7.0.7.2'
(空ファイル)
# -----------------------------------
# Nuxt.js環境構築用のDockerfile
# -----------------------------------
# ベースにするイメージ
FROM node:16-alpine3.14
# 作業用ディレクトリ
WORKDIR /var/www/html
# 必要なパッケージをインストール
RUN apk add --update \
bash \
curl
RUN npm update -g npm
# ネットワーク設定
EXPOSE 3000
ENV HOST 0.0.0.0
version: '3'
services:
# PostgreSQL用のコンテナ
db:
# ベースとなるイメージ
image: postgres:12-alpine
# 環境変数
environment:
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
# ローカル側のポート番号:コンテナ側のポート番号
ports:
- 5432:5432
# ボリューム(永続的に保存したいデータ)
# * 保存したいディレクトリをマウントする方法
# 「- ローカル側の同期させたいディレクトリ:コンテナ側の同期させたいディレクトリ」
# * 名前付きボリュームを利用する方法
# 「- ボリューム名:コンテナ側の保存させたいディレクトリ」
# (ボリューム名を末尾のvolumes(services等と同じ階層に定義)で指定する)
volumes:
- postgres_data:/var/lib/postgresql/data
# Ruby on Rails用のコンテナ
web:
# 指定したディレクトリにあるDockerfileを使ってビルドする
build: ./web
# コンテナ起動時に実行されるコマンド
# (起動していた場合は停止後に)rails serverを起動する
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
# ボリューム(永続的に保存したいデータ)
volumes:
- ./web:/MyApp
# ローカル側のポート番号:コンテナ側のポート番号
ports:
- "3000:3000"
# dbコンテナ起動後にwebコンテナを起動する
depends_on:
- db
# Nuxt.js用のコンテナ
nuxt:
build: ./front
command: bash -c "cd MyApp && yarn dev"
volumes:
- ./front:/var/www/html
# web側とポートが被るので3001に変更
ports:
- "3001:3000"
tty: true
volumes:
postgres_data:
Docker操作コマンド
Dockerを操作するにはdocker-compose.ymlファイルがあるフォルダで以下のコマンドを実行します。
# イメージ作成
docker-compose build
# コンテナ作成
docker-compose create
# コンテナ起動
docker-compose start
# イメージ作成+コンテナ作成+コンテナ起動をまとめて実行
docker-compose up -d
# イメージ作成+コンテナ作成+コンテナ起動をまとめて実行(指定したサービスだけ起動)
docker-compose run [サービス名]
# 起動と同時にコマンド実行
docker-compose run [サービス名] [コマンド]
# コンテナ停止
docker-compose down
# コンテナの稼働状況を確認
docker-compose ps
# 起動中のコンテナでコマンド実行
docker-compose exec [サービス名] [コマンド]
Ruby on Railsプロジェクトを新規作成
以下のコマンドを実行してRuby on Railsのプロジェクトを新規作成します。
# コンテナが起動済みの場合は"run" -> "exec"で読み替える
# (フロント側もまとめて全体で管理したいのでここではgit管理の対象外としておく)
docker-compose run web rails new . --force --database=postgresql --skip-bundle --skip-git
-> 追加されたファイルがローカル環境にも同期して作成される
# Gemfileが更新されているので、イメージを再作成
docker-compose build
続いて、データベースを作成します。
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: user
password: password
host: db
development:
<<: *default
database: MyApp_development
test:
<<: *default
database: MyApp_test
production:
<<: *default
database: MyApp_production
username: <%= ENV["POSTGRES_USER"] %>
password: <%= ENV["POSTGRES_PASSWORD"] %>
# データベースを作成
docker-compose exec web rails db:create
http://localhost:3000にアクセスして、以下の画面が表示されればOK。
APIの実装
コントローラクラスを作成して、ルーティングを設定します。
# コントローラを作成
docker-compose exec -it web bash
# 以下、Dockerコンテナでの操作
rails g controller samples
cd app/controllers
mkdir api
cp samples_controller.rb api/
module Api
class SamplesController < ApplicationController
# CSRFエラー対策
skip_before_action :verify_authenticity_token
# サンプルデータを返す
def sample
render json: { status: 'SUCCESS', message: 'Get sample data', data: { sample: 'hogehoge' } }
end
end
end
Rails.application.routes.draw do
namespace :api do
get "samples" => "samples#sample"
end
end
# 動作確認
curl http://localhost:3000/api/samples
-> {"status":"SUCCESS","message":"Get sample data","data":{"sample":"hogehoge"}}
Nuxt.jsプロジェクトを新規作成
以下のコマンドを実行してNuxt.jsのプロジェクトを新規作成します。
# Dockerコンテナのシェルを起動
docker-compose exec -it nuxt sh
# 以下、Dockerコンテナでの操作
npx create-nuxt-app MyApp
もしくは
yarn create nuxt-app MyApp
# インストール時の設定はお好みで
? Project name: MyApp
? Programing language: TypeScript
? Package manager: Yarn
? UI framework: Buefy
? Template engine: Pug
? Nuxt.js modules: o Axios, x PWA, x Nuxt/Content
? Linting tools: o ESLint, o Prettier, x Lint staged files, x Styleling, x Commitlint
? Testing framework: Jest
? Rendering mode: Single Page App
? Deployment target: Server
? Development tools: x
? Continuous integration: None
? Version control system: None *全体でGit使うのでここでは指定しない
# 起動
cd MyApp
yarn dev
http://localhost:3001にアクセスして、以下の画面が表示されればOK。
※UI FrameworkでBuefy以外を選んだ場合は見た目は違うものになります。
API呼出し処理の実装
プロキシを設定します。
// Dockerコンテナから見たホストマシンのIPアドレスを取得(プロキシ設定用)
const { execSync } = require('child_process')
let hostIp = execSync("cat /etc/hosts | awk 'END{print $1}' | sed -e 's/[0-9]\+$/1/g'")
// 改行を削除して、IPアドレスの最後のセグメントを1にする(なぜか上記コマンドでできない・・・)
hostIp = String(hostIp).replace('\r', '').replace('\n', '').replace(/[0-9]+$/, '1')
export default {
〜略〜
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy',
],
axios: {
baseURL: '/',
},
proxy: {
'/api': {
target: 'http://' + hostIp + ':3000/'
}
},
telemetry: false,
〜略〜
}
画面を作成します。
<template>
<div>
<p>{{ sampleData.sample }}</p>
</div>
</template>
<script>
export default {
data: () => ({
sampleData: ''
}),
created: function() {
this.$axios.get('/api/samples')
.then((res) => {
this.sampleData = res.data.data
})
.catch((error) => {
console.log(error)
}
}
}
</script>
http://localhost:3001/sampleにアクセスして、Rails側で設定した値(hogehoge)が表示されていれば成功です。
コメント
database.ymlを下記にしないとdocker-compose exec web rails db:createが失敗しますかと
・username: MyApp→user
hikariさん
ご指摘ありがとうございます。修正しました。