docker composeでRailsアプリをDocker化する

## はじめに
今回はdocker composeで既存のRailsアプリをDocker化する方法を学んだので、
アウトプットしていこうと思います。

## 前提
* Docker未使用で動作する既存Railsアプリを使用する
* 以下の環境で構築する
```
ruby: 3.2.2
Rails: 7.0.6
postgre: 12
docker-compose: 3.9
```

## 手順
 0\. Dockerのインストール & 起動 
 1\. 任意の階層に作業ディレクトリを作成 & 移動
 2\. Docker化してない既存Railsアプリをクローンしてくる
 3\. 各種必要ファイルの作成
 4\. database.ymlの編集
 5\. コンテナ起動
 6\. ブラウザで動作確認

### 0. Dockerのインストール & 起動 
Docker(for Mac)のインストールおよび起動のやり方に関しては、
下記URLを参考にしてみてください！

https://matsuand.github.io/docs.docker.jp.onthefly/desktop/mac/install/


### 1. 任意の階層に作業ディレクトリを作成 & 移動
docker化したものを置くディレクトリを作成・移動する
```
$ mkdir rails-docker && cd rails-docker
```


### 2. Docker化してない既存Railsアプリをクローンしてくる
下記の画像を参考に、`git clone`でリポジトリを自分の手元のローカルに複製する

![D7DA3347-636A-45DC-BEC8-6701F99F8C0F.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3360649/e9599135-e416-1fc3-bb72-ecbf4af0f199.png)

```
$ git clone https://github.com/TomoXiang710/rails-docker.git
```


### 3. 各種必要ファイルの作成
RailsアプリのDocker化に必要なファイル(Dockerfile, Gemfile, docker-compese.yml)を作成する

```
/raiis-docker
  ├─ Dockerfile
  ├─ Gemfile
  ├─ Gemfile.lock
  └─ Docker-compose.yml
```

#### 3.1 Dockerfileの作成
Dockerfileを作成する

```Dockerfile: Dockerfile
FROM ruby:3.2.2
RUN apt-get update -qq && apt-get install -y \
    build-essential \
    libpq-dev \
    nodejs \
    yarn
WORKDIR /rails-docker
COPY Gemfile Gemfile.lock /rails-docker/
RUN bundle install
COPY . /rails-docker/
```

* `FROM ruby: 3.2.2`
  ベースとなるDockerイメージとそのバージョンを指定
* `RUN apt-get update -qq && apt-get install -y \ build-essential \ libpq-dev \ nodejs \ yarn`
Rubyの実行に必要なパッケージをインストール
* `WORKDIR /rails-docker`
コンテナ内で作業するディレクトリを指定
* `COPY Gemfile Gemfile.lock /rails-docker/`
ホストマシンからGemfileとGemfile.lockをコンテナ内にコピー
* `RUN bundle install`
bundle installコマンドを実行
* `COPY . /rails-docker/`
ホストマシンのカレントディレクトリ下の全ファイルを、コンテナの/rails-dockerディレクトリにコピー


#### 3.2 Gemfileの作成


```ruby: Gemfile
source 'https://rubygems.org'
gem "rails", "~> 7.0.6"
```
GemfileとGemfile.lockを作成する
また、Gemfile.lockの中身は空で良い


#### 3.3 docker-compose.ymlの作成
docker-compose.ymlは`複数のコンテナ間の関係`を定義する

```yml: docker-compose.yml
version: '3.9'

volumes:
  db-data:

services:
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    ports:
      - '3000:3000'
    volumes:
      - '.:/rails-docker'
    environment:
      - 'DATABASE_PASSWORD=postgres'
    depends_on:
      - db
    tty: true
    stdin_open: true
  

  db:
    image: postgres:12
    ports:
      - '5432:5432'
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - 'POSTGRES_USER=postgres'
      - 'POSTGRES_PASSWORD=postgres' 
```

* `version: '3.9'`
docker-composeのバージョンを指定

* `volumes: db-data:` 
名前付きボリュームdb-dataの設定を始める

* `services:`
webとdbの2つのサービス（コンテナ）を定義

* `web:`
webサービス（コンテナ）の設定を始める

* `build: .`
カレントディレクトリ（.）にあるDockerfileに基づいてDockerイメージをビルドする

* `command: bundle exec rails s -p 3000 -b '0.0.0.0'`
コンテナが起動する際に実行されるコマンドを指定し、Railsサーバを起動

* `ports: - 3000:3000`
ホストの3000番ポートとコンテナの3000番ポートをマッピングする。ホストのブラウザから`http://localhost:3000`でRailsアプリケーションにアクセス

* `volumes: - .:/rails-docker`
ホストのカレントディレクトリ（.）とコンテナ内の/rails-dockerディレクトリをマウントする

* `environment: - 'DATABASE_PASSWORD=postgres'`
コンテナ内で使用する環境変数を設定。ここでは、DATABASE_PASSWORDをpostgresで設定

* `depends_on: - db`
webサービスがdbサービスに依存していることを示す。dbサービスが先に起動した後でwebサービスが起動

* `tty: true`と`stdin_open: true`
これらのオプションはコンテナ内での対話型プロセスを可能にする

* `db:`
dbサービス（コンテナ）の設定を始める

* `image: postgres:12`
バージョン12のpostgreSQLイメージ（Dockerイメージ）を使用

* `ports: - 5432:5432`
ホストの5432番ポートとコンテナの5432番ポートをマッピングする

* `volumes: - db-data:/var/lib/postgresql/data`
名前付きボリュームdb-dataとコンテナ内の/var/lib/postgresql/dataディレクトリをマウントすることで、データベースのデータが永続化される

* `environment: - 'POSTGRES_USER=postgres' - 'POSTGRES_PASSWORD=postgres'` 
環境変数を設定


### 4. database.ymlの編集
database.ymlを編集する

```yml: database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  user: postgres
  password: <%= ENV['DATABASE_PASSWORD'] %>
  port: 5432
  # 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`・`user`・`password`を追加しています
`user`と`password`は環境変数に置き換えています


### 5. コンテナ起動
ここまでできたら、実際にコンテナを立ち上げる
<br>

イメージのビルド&コンテナの作成と起動
```
docker compose up -d
```

コンテナ内へ入る
```
docker compose exec web bash
```

dbの作成
```
rails db:create
```

dbの更新
```
rails db:migrate
```

### 6. ブラウザで動作確認
ブラウザ上で`localhost:3000`でブラウザが立ち上がるか確認する

![8C6D0D20-44B6-416D-8ABA-06050664EDC8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3360649/c3a5960a-d6f0-9e27-5e5c-3e212abf7a0f.png)


## まとめ
一連の流れ
 0\. Dockerのインストール & 起動 
 1\. 任意の階層に作業ディレクトリを作成 & 移動
 2\. Docker化してない既存Railsアプリをクローンしてくる
 3\. 各種必要ファイルの作成
 4\. database.ymlの編集
 5\. コンテナ起動
 6\. ブラウザで動作確認