LoginSignup
4
1

More than 1 year has passed since last update.

Rails7 Mysql8 React TypeScriptで作る Docker環境

Last updated at Posted at 2022-08-19

はじめに

近しい記事はあれど、欲しい環境の記事を見つけられなかった
妥協して近しい記事をコピペで使おうとしたらエラーで動かなかった。
この際勉強にもなるし、自分で組んでみようということで作成しました。

前提

M1 Mac
基本的なDockerコマンドはわかる
エラーでハマった箇所を中心に少しだけ説明も入れる

求めた条件

Rails7 API
Mysql8 (認証プラグインを旧バージョンに変更)
React TypeScriptを使用する
backend frontend docker-compose.ymlのシンプルな構成
docker compose run <サービス> /bin/sh等でコンテナに入って直接作業するのはなし
最近発生しているbundler特有のエラーを抑制する記載もいれたい

構成

backend
 - Dockerfile
frontend
 - Dockefile
docker-compose.yml

バックエンド

Dockerfile

FROM ruby:3.1
ARG RUBYGEMS_VERSION=3.3.20

# WORKDIRは指定したディレクトリがなければ自動で作成する
WORKDIR /backend
COPY Gemfile* /backend/

# Bundlerのversionが起因してエラーが発生するのを防いでいる (結構苦労した)
# 過去には問題なく動いていた環境で急に動かなくなった人もいたみたい
RUN gem update --system ${RUBYGEMS_VERSION} && \
    bundle install
COPY . /backend

# rails特有のバグを避けるために必要
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]

EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]
frontent/Dockerfile
FROM node:18.7.0-alpine3.16
WORKDIR /frontend
RUN npm i -g create-react-app

Gemfile

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

Gemfile.lock

# 空で良い

entrypoint.sh

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /backend/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

フロントエンド

Dockerfile

FROM node:18.7.0-alpine3.16
WORKDIR /frontend

# create-react-appのinstallはdocker compose run時にしても良いが
# 今回はImageの時点で入れている
# ここは変更してもよさそう
RUN npm i -g create-react-app

docker-compose.yml

version: '3.8'
services:
  db:
    image: mysql:8.0.29
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - ./tmp/db:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
    ports:
      - "3306:3306"

  backend:
    build: ./backend/
    volumes:
      - ./backend:/backend
    ports:
      - "3001:3000"
    depends_on:
      - db

  frontend:
    build: ./frontend/
    volumes:
      - ./frontend:/frontend
    command: sh -c "npm start"
    ports:
      - "3000:3000"

コマンド

バックエンド

# コンテナ内で railsアプリを作成
docker compose run --rm backend rails new . --force --no-deps -d mysql --api
# config/database.ymlを編集してコンテナのmysqlに接続する
password: root
host: db
# Gemfileが更新されたので再度buildする
docker compose build

# DBを作成
docker compose run --rm backend rails db:create

フロントエンド

# Dockerfileをrootに移す アプリを作成 Dockerfileを元に戻す作業を行なっている
# create-react-app . する際余計なファイルが存在すると作成してくれないのでこの形にしている(苦労した)
docker compose run --rm frontend sh -c "mv Dockerfile .. && npx create-react-app . && mv /Dockerfile /frontend/Dockerfile"

全てのコンテナを立ち上げる

docker compose up -d

http://localhost:3000rails
http://localhost:3001react

知識系 小ネタ

docker comose run <サービス> <コマンド>で複数のコマンドを実行したい時
sh -c "A && B"とする必要がある
A && Bとすると2個目以降はホストで実行されてしまう。

ymlcommandが設定されている場合
docker compose rundocker compose upではDockerfileCMDは無視される
docker container <Image>名で起動する場合はCMD
docker compose run <コマンド>とする場合は設定したコマンドを優先する

ちょっと脱線

最近はバックエンドとフロントエンドのリポジトリを分けて開発することも多いようです。
バックエンドのAPIだけDocker化して別々のプロジェクトとして連携したほうがCI/CDの構築が簡単
コミットにバックエンドとフロントエンドが混ざることがなくなる。等利点があるようですので
どちらを利用するか考えないとですね。
自分はこの環境を作っている際に知ったのですが、最後まで完成させたくて時間を使ってしまった・・・

参考

今回は10サイト以上見ましたが、その中でも特に参考にしたものを貼っておきます。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1