Ruby on Rails、Nuxt.js、MySQLのDocker環境を作成します。
Rails、Nuxtのalpine環境の構築手順はそれぞれだと多くあるのですが、まとまったものがあまり ない 見つからなかったので、復習を兼ねてポストを作成します。
準備
ディレクトリ作成
作業ディレクトリは任意です。
$ NEW_APP=rails-nuxt-app #任意のアプリ名
$ mkdir ${NEW_APP}
$ cd ${NEW_APP}
$ mkdir ./backend ./frontend
backend
はRails用、frontend
はNuxt用のディレクトリです。
まずは下記のファイルを修正していきます。
.
├ backend
│ ├ Dockerfile
│ ├ Gemfile
│ └ Gemfile.lock
│
├ frontend
│ └ Dockerfile
│
├ docker-compose.yml
└ .env
docker-compose.yml
.env
docker-compose.ymlで参照する環境変数を記載します。
ここではMySQLのrootパスワード、RailsおよびNuxt環境のホスト、ポート番号のみ定義します。
RailsとNuxtは、共にデフォルトのポートが 3000
番なので、後の利便性のためにいずれかを変えておきます。
(本記事ではNuxt側を 8080
に変更)
MYSQL_ROOT_PASSWORD=password
BACKEND_HOST=0.0.0.0
BACKEND_PORT=3000
FRONTEND_HOST=0.0.0.0
FRONTEND_PORT=8080
./docker-compose.yml
.envで定義した変数を参照しています。
docker-compose.ymlの environment
、 Dockerfileの ENV
で同じ環境変数が定義されていた場合は、前者が使用されます。
(本記事ではDockerfile単体でもイメージ作成できるように環境変数の記載を残していますが、docker-compose.ymlに定義されていれば問題ありません)
下記はDockerボリュームを作成します。
- mysqlのdatadir
- rubyのgem_home
- nodeのnode_modules
version: '3'
services:
db:
image: mysql:5.7.27
restart: always
volumes:
- db-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
backend:
build: ./backend
ports:
- ${BACKEND_PORT}:3000
command: /bin/sh -c "rm -f /app/tmp/pids/server.pid && bundle exec rails s -b ${BACKEND_HOST}"
volumes:
- ./backend:/app
- backend-bundle:/usr/local/bundle
environment:
- HOST=${BACKEND_HOST}
- PORT=${BACKEND_PORT}
depends_on:
- db
tty: true
stdin_open: true
frontend:
build: ./frontend
ports:
- ${FRONTEND_PORT}:8080
command: /bin/sh -c "yarn dev"
volumes:
- ./frontend:/app
- frontend-node_modules:/app/node_modules
environment:
- HOST=${FRONTEND_HOST}
- PORT=${FRONTEND_PORT}
tty: true
volumes:
db-data:
backend-bundle:
frontend-node_modules:
backend
Rails環境構築のためのファイルを準備します。
./backend/Gemfile
Railsのバージョンのみ指定しておきます。
source 'https://rubygems.org'
gem 'rails', '5.2.3'
./backend/Gemfile.lock
空ファイルをtouchしておけばOKです。
./backend/Dockerfile
Alpine Linuxのパッケージは最低限のものだけインストールします。
開発を進めるうちにgemのインストールで依存エラーが発生した場合には、不足パッケージを都度追加しましょう。
面倒な場合は build-base
を RUNTIME_PACKAGES
に移しておけば一旦は大丈夫です。
FROM ruby:2.6.3-alpine
ENV RUNTIME_PACKAGES "mysql-client mysql-dev tzdata nodejs"
ENV DEV_PACKAGES "build-base curl-dev"
ENV APP_HOME /app
ENV TZ Asia/Tokyo
ENV HOST 0.0.0.0
ENV PORT 3000
WORKDIR ${APP_HOME}
ADD Gemfile ${APP_HOME}/Gemfile
ADD Gemfile.lock ${APP_HOME}/Gemfile.lock
RUN apk update \
&& apk upgrade \
&& apk add --update --no-cache ${RUNTIME_PACKAGES} \
&& apk add --update --no-cache --virtual=.build-dependencies ${DEV_PACKAGES} \
&& bundle install -j4 \
&& rm -rf /usr/local/bundle/cache/*.gem \
&& find /usr/local/bundle/gems/ -name "*.c" -delete \
&& find /usr/local/bundle/gems/ -name "*.o" -delete \
&& apk del --purge .build-dependencies \
&& rm -rf /var/cache/apk/*
COPY . ${APP_HOME}
EXPOSE ${PORT}
CMD ["rails", "server", "-b", ${HOST}]
frontend
./frontend/Dockerfile
FROM node:12.9.0-alpine
ENV APP_HOME /app
ENV PATH ${APP_HOME}/node_modules/.bin:$PATH
ENV TZ Asia/Tokyo
ENV HOST 0.0.0.0
ENV PORT 8080
WORKDIR ${APP_HOME}
ADD . ${APP_HOME}
RUN apk update \
&& apk upgrade \
&& yarn install \
&& rm -rf /var/cache/apk/*
EXPOSE ${PORT}
CMD ["yarn", "dev"]
アプリケーション作成
Rails、Nuxt環境にプロジェクトを作成します。
docker-compose run
を実行したタイミングで、それぞれのDockerイメージがbuildされ、さらにコンテナが立ち上がります。
--no-deps
... docker-compose.ymlで depends_on
or links
指定するサービスは起動しない。
--rm
... 処理を終えたコンテナを自動的に削除。
backend
アプリケーション作成
rails new
でRailsアプリケーションを作成します。
--api
オプションでAPIモードにしていますが、不要な方は外してください。
$ docker-compose run --no-deps --rm backend rails new . --force --api --database=mysql --skip-bundle
DB接続のため、下記のファイルを修正します。
.
└ backend
├ config
│ └ database.yml
├ Gemfile
└ .env
./backend/.env
docker-compose.ymlで参照している MYSQL_ROOT_PASSWORD
と同じもの設定します。
MYSQL_ROOT_PASSWORD=password
./backend/Gemfile
.envから環境変数を読み込むdotenv-railsというgemを追加します。
~~省略~~
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
gem "dotenv-rails" #追加
end
~~省略~~
./backend/config/database.yml
DBへのアクセスに使用するパスワードを、環境変数から取得します。
~~省略~~
default: &default
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: <%= ENV.fetch("MYSQL_ROOT_PASSWORD") { '' } %> #環境変数を参照するように修正
host: db #localhostからdocker-compose.ymlのサービス名に修正
~~省略~~
frontend
アプリケーション作成
npx
でNuxtアプリケーションを作成します。
後から追加/変更できるので、このタイミングではEnterキー連打でOKです。
$ docker-compose run --rm frontend npx create-nuxt-app .
~~省略~~
create-nuxt-app v2.10.0
✨ Generating Nuxt.js project in .
? Project name #アプリ名 <Enter>
? Project description #任意 <Enter>
? Author name #任意 <Enter>
? Choose the package manager #Yarn <Enter>
? Choose UI framework #None <Enter>
? Choose custom server framework #None <Enter>
? Choose Nuxt.js modules #(Nothing) <Enter>
? Choose linting tools #(Nothing) <Enter>
? Choose test framework #None <Enter>
? Choose rendering mode #Universal (SSR) <Enter>
? Choose development tools #(Nothing) <Enter>
Dockerイメージ作成
アプリケーション作成時にできたDockerボリュームは削除しておきます。
$ docker-compose down --volume
# もしくは docker volume rm ボリューム名
各ファイルを修正した状態で、Dockerイメージをビルドします。
$ docker-compose build
docker-compose.ymlで build
を指定しているbackendとfrontendのイメージが作成されたことを確認します。
$ docker images --format "{{.Repository}}\t{{.CreatedSince}}" ${NEW_APP}*
rails-nuxt-app_frontend About a minutes ago
rails-nuxt-app_backend About a minutes ago
Hello World
最後にDockerコンテナを起動し、Rails、NuxtアプリケーションのHelloWorldを確認します、
docker-compose.ymlで定義したサービスを -d
オプション(デタッチモード)でバックグラウンド起動します。
$ docker-compose up -d
プロセスが立ち上がっていることを確認します。
$ docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------------
rails-nuxt-app_backend_1 /bin/sh -c rm -f /app/tmp/ ... Up 0.0.0.0:3000->3000/tcp
rails-nuxt-app_db_1 docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp
rails-nuxt-app_frontend_1 docker-entrypoint.sh /bin/ ... Up 0.0.0.0:8080->8080/tcp
失敗している場合は docker-compose logs
などで原因を探りましょう。
backend
RailsアプリケーションのDBを作成します。
$ docker-compose exec backend rails db:create
Created database 'app_development'
Created database 'app_test'
ブラウザで http://localhost:3000/ を開きます。
frontend
ブラウザで http://localhost:8080/ を開きます。
お疲れさまでした。
次回は GraphQL の導入について投稿したいと思います。