Rails & Nuxt.jsのDocker環境をalpineイメージで構築する

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

MYSQL_ROOT_PASSWORD=password

BACKEND_HOST=0.0.0.0
BACKEND_PORT=3000

FRONTEND_HOST=0.0.0.0
FRONTEND_PORT=8080
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)

Rails環境構築のためのファイルを準備します。

source 'https://rubygems.org'

gem 'rails', '5.2.3'
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(nuxt)

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 & links 指定するサービスが起動しないようにします。
--rm オプションで、アプリケーション作成を終えたコンテナが自動的に削除されるようにします。

backend(rails)

アプリ作成

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
MYSQL_ROOT_PASSWORD=password
## 中略 ##

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

## 中略 ##
## 中略 ##

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(nuxt)

アプリ作成

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 "\t" ${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)

RailsアプリケーションのDBを作成します。

$ docker-compose exec backend rails db:create
Created database 'app_development'
Created database 'app_test'

ブラウザで http://localhost:3000/ を開きます。

rails-helloworld

frontend(nuxt)

ブラウザで http://localhost:8080/ を開きます。

nuxt-helloworld


お疲れさまでした。
次回は GraphQL の導入について投稿したいと思います。

← Blog