WebアプリをDocker化する方法 (rails)

## はじめに
今回github上にある既存のrailsプロジェクトをdocker化したので自身のアウトプットも含め記事にしました。

簡単にDockerとは開発環境や実行環境などをチームで同じものを使うための（コンテナ型仮想化という技術を用いて開発する）アプリケーションです。

最近の技術にDockerがよく使われるようになっていてモダンな開発現場には必須知識だそうです。

大まかなコードはDocker document jpを参考にしました。

https://docs.docker.jp/compose/rails.html

## Docker化
railsアプリをdocker化していきます。
既存railsアプリに新規作成するファイル
* Dockerfile 
* docker-compose.yml

編集確認するファイル
* Gemfile
* database.yml


#### Gemfile
今回railsを使うということでrubyのバージョン確認とそれに対応したrailsのバージョンであるかを確認します。

```ruby:Gemfile
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby "3.2.2"

# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.0.6"
.
.
.
```
このアプリのrubyのバージョンは3.2.2とわかりましたので、Dockerfileに使います

#### Dockerfile

``` Docker:Dockerfile
FROM ruby:3.2.2
RUN apt-get update && apt-get install -y \
    build-essential \
    libpq-dev \
    nodejs
RUN mkdir rails-docker
WORKDIR /rails-docker
COPY . Gemfile Gemfile.lock /rails-docker/
RUN bundle install
```
* FROM: ベースとなるdocker imageを指定する。Docker hubを確認すればlinuxも導入されていることがわかる
* RUN: コマンドを実行
* WORKDIR: dockerfileでコマンドを実行する際基準となるdirを指定。
なかったら作成される。
* COPY: docker内へホストのファイルをコピーする。

COPYと同じようにADDというDSLがあるがADDは主にtarの圧縮ファイルを圧縮して解凍したい時に使います。
故にホストのファイルorディレクトリをdockerのファイルシステムに加えるときはCOPYを基本的に使います。

#### docker-compose.yml
docker-compose.ymlファイルはコンテナをどのように起動するかについて記述します。
docker-compose.ymlには型があります。
```yml:書き方
versinon: 'n'
services: 
    service_name1:
        service_name1のパラメータ
        service_name1のパラメータ
        .
        .
    service_name2:
        service_name2のパラメータ
        service_name2のパラメータ
        .
        .
```
* version: ここのnにはdocker-composeのバージョンについて記述する
* services:  サービスとはアプリケーションとして実行したいコンテナのこと。でservicesはその一覧のこと

:::note info
service_nameは任意
:::

今回は以下のように記述しました。
``` yml:docker-compose.yml
version: '3'
services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/myapp
    command: > 
      /bin/sh -c "rm -f /tmp/pids/server.pid &&
      bundle exec rails s -p 3000 -b '0.0.0.0' "
    environment:
      - 'DATABASE_PASSWORD=postgres'
    depends_on: 
      - db
    links: 
      - db
    tty: true
    stdin_open: true

  db:
    image: postgres
    environment:
      - 'POSTGRES_USER=postgres'
      - 'POSTGRES_PASSWORD=postgres'

```

* `build: .` &emsp;ビルドするビルドコンテキストを指定する。今回はカレントディレクトリを指定
* `ports:` 
   `- "3000:3000"` 
ポートの割り当てを指定します。ホストのポート番号 : コンテナのポート番号
* `volumes:`
    `- .:/myapp` 
ホストのdirとコンテナのdirを共有するために使われる&emsp;ホストdir : コンテナdir あくまでファイルはホストにある
* `command: > `
      `/bin/sh -c "rm -f /tmp/pids/server.pid &&
      rails db:migrate && 
      bundle exec rails s -p 3000 -b '0.0.0.0'"`
```
/bin/sh -c "rm -f /tmp/pids/server.pid"
```
開発用webサーバを起動したときserver.pidに情報が書き込まれ、書き込まれている状態だとサーバー起動中と判断されます。よって、エラーを起こさないためにサーバー起動の際server.pidを削除します.

ただ立ち上げるたびに毎度createする必要はないため、初めて立ち上げるときのみcreateするようにして、DB反映、サーバー起動をここに記述します。


* `environment:`
 `- 'DATABASE_PASSWORD=postgres'`
コンテナ内で使用される環境変数の設定。
* `depends_on:` 
`- db`
サービスの依存関係を定義するために使用
* `links:` 
`- db `
webとdbが通信できるようにする。
* `tty: true`
* `stdin_open: true`
docker run -itと同義。

#### database.yml
``` yml:database.yml
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 } %>

```
* `port` : 5432はPostgreSQLのTCPポート番号
* `password` : 接続する際に使用するパスワード
* `pool` : DBに接続するコネクションプールの上限数。
コネクションプールとは、DBの接続情報を維持しておく機能。

## 立ち上げ
imageファイルを作成します
```
docker-compose build 
```
DBを作成します
```
docker-compose run --rm web rails db:create
```
DB反映、サーバー立ち上げを行います.(.ymlの記述内容を実行)
```
docker-compose up -d
```
ブラウザでhttp://localhost:3000/

これでrailsのdocker化が完了です

## 停止
一時的に停止するときは
```
docker-compose stop
```
その後再度起動するときは(rails db:createはいらない)
```
docker-compose up -d
```
完全停止するときは
```
docker-compose down
```

です。

## 終わりに

dockerがここまでできるようになれたのはUdemyの講座が良かったからだと思います。
おすすめです。

https://www.udemy.com/course/aidocker/learn/lecture/20294617#overview

間違い等があれば指摘していただければ幸いです。