Rails7（esbuild + Tailwind + MySQL）をDocker Composeで環境構築する

[株式会社TECH LUCK](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)という会社で代表兼エンジニアをしている齊藤です。

DXプロジェクト、開発プロジェクト、Rails開発などでお困りごとがありましたら[弊社HP](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)からご相談をいただけますと幸いです。
以下のような問題に対応することが可能です。
- プロジェクトでRailsエンジニアが足りなくて困っている
- Railsのバージョンアップをしたいがノウハウ・リソースが足りなくて困っている
- オフショア開発をしているが、要件の齟齬やコード品質が悪いので改善したい

また、Railsエンジニアも募集しておりますので、興味がありましたら[弊社HP](https://techluck.co.jp/?utm_source=qiita&utm_medium=article&utm_campaign=myarticle)からご連絡いただけますと幸いです。

# 前提

Rails7の環境構築でesbuild,Tailwind, MySQLでの構成の際に、Docker Composeで環境構築する際にハマったところなどをまとめておきました。

開発環境は以下の通りです。
- M1 Mac
- Ruby v3.2（RailsのDockerコンテナの中でのバージョン）
- Rails v7.0.5（RailsのDockerコンテナの中でのバージョン）
- Node v18.16.1（RailsのDockerコンテナの中でのバージョン）
- MySQL v8.0.32（MySQLコンテナの中でのバージョン）

# Docker Composeを実行する前に作成・変更が必要なファイル

## entrypoint.sh
以下の記述で作成します。

```sh:entrypoint.sh
#!/bin/bash
set -e

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

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

## Dockerfile
以下の記述で作成します。

```Dockerfile:Dockerfile
FROM ruby:3.2.0

RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs
RUN apt-get install -y default-mysql-client
RUN npm install -y --global yarn

WORKDIR /myapp
COPY . /myapp

RUN bundle install
RUN yarn install

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"]
```

## Procfile.dev
以下の記述で変更します。

```Procfile.dev
web: bin/rails server -b 0.0.0.0 -p 3000 # ここを変更
js: yarn build --watch
css: yarn build:css --watch
```

`web: bin/rails server -b 0.0.0.0 -p 3000` でDockerコンテナ内でポート：3000番でポートフォワーディングしており、ホストOSからのアクセスを受け付けるようになります。

`js: yarn build --watch` でDockerコンテナ内でJSの変更を監視して、逐一ビルドしてくれるようになります。これによって、JSを変更したら都度ビルドしないと変更がなされないということがなくなります。

`css: yarn build:css --watch` でDockerコンテナ内でCSSの変更を監視して、逐一ビルドしてくれるようになります。これによって、CSSを変更したら都度ビルドしないと変更がなされないということがなくなります。


## database.yaml
以下のように変更します。

```yaml:config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock

development:
  <<: *default
  host: db #ここを追加
  database: instalike_development

test:
  <<: *default
  host: db #ここを追加
  database: instalike_test
```

## docker-compose.yml
以下の記述で作成します。

```yaml:docker-compose.yml
version: '3.7'
services:
  db:
    image: mysql:8.0.32
    command: --default-authentication-plugin=mysql_native_password
    container_name: db
    ports:
      - "4306:3306"
    volumes:
      - db:/var/lib/mysql
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
    security_opt:
      - seccomp:unconfined
  app:
    build: .
    stdin_open: true
    container_name: app
    tty: true
    volumes:
      - .:/myapp
      - bundle:/usr/local/bundle
      - node_modules:/myapp/node_modules
    command: bash -c "rm -rf tmp/pids/server.pid && ./bin/dev"
    depends_on:
      - db
    ports:
      - "3000:3000"
volumes:
  db:
    driver: local
  bundle:
    driver: local
  node_modules:
    driver: local
```

### appのcommandについて
`./bin/dev`を実行しています。
これで `Procfile.dev` を実行することになり、Railsサーバーの実行と、JS・CSSの監視とビルドを行うことになります。


### node_modulesについて
`yarn install`した際に`node_modules`を`volumes`に保存するようにします。
これをしないと、`docker compose up`の途中の`./bin/dev`の実行の際に以下のようなエラーが出てきます。

```bash:エラー文
app  | 12:42:23 js.1   | $ esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=/assets --watch
app  | 12:42:23 css.1  | $ tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css --minify --watch
app  | 12:42:23 js.1   | /bin/sh: 1: esbuild: not found
app  | 12:42:23 js.1   | error Command failed with exit code 127.
app  | 12:42:23 js.1   | info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
app  | 12:42:23 css.1  | /bin/sh: 1: tailwindcss: not found
app  | 12:42:23 css.1  | error Command failed with exit code 127.
app  | 12:42:23 css.1  | info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
app  | 12:42:24 js.1   | exited with code 127
app  | 12:42:24 system | sending SIGTERM to all processes
app  | 12:42:24 css.1  | exited with code 127
```

これは`node_modules`が保存されていないために、`yarn build --watch`の実行がエラーになってしまうためです。
そのため、`volumes`を使って`node_modules`を永続化させるようにします。


# Docker Composeの実行
必要なファイルが揃ったら、以下のコマンドを実行してDocker Composeでアプリケーションを起動させます。

```bash:ターミナル
docker compose build --no-cache
docker compose up

# 以下は別のタブで実行する。
docker compose run app rails db:create rails db:migrate
```

以上です。