DockerでRailsアプリを作る方法

## Overview
RailsアプリをゼロからDockerで作ったので、記録ように整理しまーす。

## Motivation/Context
久しぶりにrailsアプリをゼロから作る機会がありました。
最近はRails8がリリースされたみたいですね。
手元にすでにDockerでRailsを作った環境があったので、それを応用しました。

基本的な流れはこんな感じで考えています。
1. 必要最低限のrubyだけ入ったコンテナを作る。
1. コンテナ内で手動でrailsをインストールしてアプリの雛形を作る。
1. Dockerfile,docker-compose.ymlで起動のスクリプトを組む。

## Get started!!

さあ、実際に始めてみましょう。

### Dockerコンテナの作成

```yml
FROM ruby:3.4.1

# 必要最低限のツールを入れる
RUN apt-get update -qq && apt-get install -y sqlite3 vim nodejs npm

# アプリケーションディレクトリを作成
RUN mkdir rails-app

# アプリケーションディレクトリを作業用ディレクトリに設定
WORKDIR /rails-app
# ADD Gemfile ./Gemfile
# ADD Gemfile.lock ./Gemfile.lock
# RUN bundle install
ADD . .

# RUN npm install

EXPOSE 3000
```

`docker-compose.yml`
```yml
version: '3'
services:
  db:
    image: postgres:17.2
    environment:
      TZ: Asia/Tokyo
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    restart: always
  rails:
    build:
      context: .
    # command: bash setup.sh
    environment:
      TZ: Asia/Tokyo
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      DEVELOPMENT_HOST: $DEVELOPMENT_HOST
      DEVELOPMENT_PORT: $RAILS_PORT
      CLOUDINARY_CLOUD_NAME_TRANNE: $CLOUDINARY_CLOUD_NAME_TRANNE
      CLOUDINARY_API_KEY_TRANNE: $CLOUDINARY_API_KEY_TRANNE
      CLOUDINARY_API_SECRET_TRANNE: $CLOUDINARY_API_SECRET_TRANNE
    volumes:
      - .:/rails-app
      - /etc/passwd:/etc/passwd:ro
      - /etc/group:/etc/group:ro
    ports:
      - "${RAILS_PORT}:3000"
    depends_on:
      - db
    tty: true
```

`.env`
```
RAILS_PORT: 7001
DEVELOPMENT_HOST: http://localhost
```


:::note
ポイント
1. Gemfile, Gemfile.lockあたりはまだ存在しないからコメントアウト
1. railsコンテナにはrubyしか入っていない
1. 必要な情報は環境変数ファイルとして.envに保存
:::



### railsコンテナでrailsを手動インストール
```bash
# まずはコンテナに侵入
$ docker compose up -d --build
$ docker compose exec rails bash

# ここからはコンテナ内
$ ruby -v
$ gem install rails
$ rails new . --database=postgresql
```

:::note
ポイント
1. DBはpostgreを使うので最初から設定しておく
:::

### アプリの起動をスクリプト化
`Dockerfile`
```yml
FROM ruby:3.4.1

# 必要最低限のツールを入れる
RUN apt-get update -qq && apt-get install -y sqlite3 vim nodejs npm

# アプリケーションディレクトリを作成
RUN mkdir rails-app

# アプリケーションディレクトリを作業用ディレクトリに設定
WORKDIR /rails-app
ADD Gemfile ./Gemfile
ADD Gemfile.lock ./Gemfile.lock
RUN bundle install
ADD . .

# RUN npm install

EXPOSE 3000
```

`/setup.sh`
```sh
#!/bin/bash

rm -f tmp/pids/server.pid && \
rails db:create && \
rails db:migrate && \
rails db:seed && \
# npm run build && \
bundle exec rails s -p 3000 -b '0.0.0.0'
```

コンテナのDBを使うように設定

`config/database.yml`
```diff
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
+  host: db
+  username: <%= ENV["POSTGRES_USER"] %>
+  password: <%= ENV["POSTGRES_PASSWORD"] %>
```

書きコマンドを繰り返してスクリプトを微調整
```bash
$ docker compose down
$ docker compose up -d --build
```

### できた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320824/bd7d6981-ef21-492a-dea2-5f498954b129.png)

### Githubにcommitする準備


`.gitignore`
```diff
+ .env
```

```bash
$ mv .env .env.example
```