docker-composeで開発環境を構築するやり方

本記事ではrails+postgreSQLを使用したアプリケーションをdocker-composeを使用してdocker化するやり方を記載する。

- 使用ファイル構成
![スクリーンショット 2023-09-18 20.21.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3510594/940a6555-c966-775d-a8aa-af72a55e522c.png)
このRailsのアプリケーションをdocker化する

- 作成するファイル
```Dockerfile:Dockerfile
FROM ruby:3.2.2
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile Gemfile.lock /myapp/
RUN bundle install

```
`apt-get update`でパッケージリストを更新してその後に必要なパッケージを`apt-get install`でインストールします。
`-y`オプションをオプションを指定して確認プロンプトを自動でスキップする。

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

volumes:
  db-data:

services:
  db:
    image: postgres:12
    volumes:
      - 'db-data:/var/lib/postgresql/data'
    environment:
      - 'POSTGRES_USER=postgres'
      - 'POSTGRES_PASSWORD=postgres'
  web:
    build: .
    command: >
      bash -c "rm -f tmp/pids/server.pid && rails db:create && rails db:migrate && rails s -b 0.0.0.0"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    environment:
      - 'DATABASE_PASSWORD=postgres'
    depends_on:
      - db
    tty: true
    stdin_open: true
    links:
      - db

```

```
volumes:
  db-data:
```
コンテナを終了or削除してもデータを保持できるようデータベースの中身をホストへ同期します。

まずはwebコンテナについてです。webコンテナは名前の通りwebサーバーとなるコンテナで、ここでrailsを実行しています。

```yml:WEB
  web:
    build: .
    command: >
      bash -c "rm -f tmp/pids/server.pid && rails db:create && rails db:migrate && rails s -b 0.0.0.0"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    environment:
      - 'DATABASE_PASSWORD=postgres'
    depends_on:
      - db
    tty: true
    stdin_open: true
    links:
      - db
```
```
command: >
      bash -c "rm -f tmp/pids/server.pid && rails db:create && rails db:migrate && rails s -b 0.0.0.0"
```
`command`ではコンテナ起動時に実行するコマンドを指定できます。以下のコマンドが順番に実行されます。

`bash -c`
以降の文字列をシェルで実行する

`rm -f tmp/pids/server.pid`
前回のサーバーのプロセスID（PID）ファイルを強制的に削除します。これは、アプリケーションサーバーが以前のセッションからクリーンアップされなかった場合の問題を防ぐためのものです。server.pidが存在すると、WEBサーバが起動中（プロセスがある）と判断され、下記のエラーが発生します。
`A server is already running. Check /tmp/pids/server.pid.　Exiting`

`rails db:create`
Railsのデータベースを作成します。

`rails db:migrate`
データベースのマイグレーションを実行します。

`rails s -b 0.0.0.0`
Railsのサーバーを起動します。

```
    volumes:
      - .:/myapp
```
ホストPCとコンテナ内のファイルを同期します。ホストPCのカレントディレクトリとコンテナ内の/myapp配下を同期しています。

```
environment:
      - 'DATABASE_PASSWORD=postgres'
```
コンテナ内で扱う環境変数を設定します。データベースのパスワードとして'postgres'を設定しています。

```
tty: true
stdin_open: true
```
`docker run -it`と同義

```
depends_on:
  - db
```
コンテナ間の依存関係を設定しています。dbコンテナが起動した後webコンテナを起動します
"webコンテナはdbコンテナが必要なのでdbコンテナから立ち上げてね”という意味になります。

```
links:
  - db
```
webコンテナとdbサービスが通信できるようにリンクします。

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

```
volumes:
      - 'db-data:/var/lib/postgresql/data'
```
前述のdb-dataボリュームをPostgresのデータディレクトリにマウントします。

# config/database.yml

```yml:database.yaml
.
.
.
# 開発環境
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  user: postgres
  port: 5432
  password: <%= ENV.fetch("DATABASE_PASSWORD") %>
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
.
.
.
```
`adapter`にはRailsアプリケーションが使用するデータベースの種類を設定します。今回はpostgresを使用するので'postgresql'としています。
ちなみにmysqlの場合は'mysql12'、sqliteの場合は'sqlite3'のようにデータベースの種類によって値が決まっています。

`port`は'5432'とします。これはPostgreSQLデータベースのデフォルトのTCPポート番号です。postgresを使用する場合'5432'を使用するのが一般的なようです。

`password`はdocker-compose.ymlのdbコンテナ部分で指定した'POSTGRES_PASSWORD=postgres'とリンクしています。

# アプリケーションの立ち上げ

ここまで完了すればあとは`docker-compose up -d`でコンテナを起動しlacalhost:3000でアプリケーションにアクセスできるようになります。
`-d`オプション:コンテナをバックグランドで動作させる

以上がWebアプリケーション（Ruby on Rails7.6 × postgres12）をdocker化する手順となります。