開発環境のRailsアプリをDockerコンテナで起動してみた

#目次
[1.はじめに](#はじめに)
[2.前提](#前提)
[3.大まかな手順](#大まかな手順)
[4.dockerの設定ファイル作成](#dockerの設定ファイル作成)
[5.アプリ用コンテナとデータベース用コンテナの接続設定](#アプリ用コンテナとデータベース用コンテナの接続設定)
[6.コンテナ起動](#コンテナ起動)
[7.まとめ](#まとめ)

#はじめに
先日、Railsで学習系のWebアプリを作成しましたが、環境構築の際は、何かしらエラーが出ては原因を調べて解消の繰り返しでした。様々な知識を得る良い機会ではあったのですが、今後、開発をする際はより効率的にできたらなという思いがあります。解決手段の１つとしては「Docker」が挙げられるかと思います。次にアプリ開発をする際は初期段階からDockerを用いた開発をしたいと考えていますが、まずは今回作成した既存のアプリをDockerコンテナで起動できないか試してみましたので、記録として残します。

#前提
・開発端末にてDockerをインストール済であること
・以下の手順における各ソフトウェアバージョンは次の通り
・Ruby: 2.6.5
・Rails: 6.0.3
・MySQL: 5.6
・今回は既存アプリを2種類のDockerコンテナ(アプリ用コンテナ、データベース用コンテナ)を連携させて起動する

#大まかな手順
①dockerの設定ファイル(Dockerfileとdocker-compose.yml)作成
②アプリ用コンテナとデータベース用コンテナの接続設定
③コンテナ起動

#dockerの設定ファイル作成
まずは既存アプリのフォルダ階層にて以下、2種類のファイルを作成します。
■ Dockerfile
→Dockerイメージの素となるファイル。ここに記述された内容で、まるっと環境のイメージが生成されます。今回はアプリ用コンテナの素となるように記述していきます。

■ docker-compose.yml
→複数のコンテナを管理する際に使用するファイル。今回はアプリ用コンテナとデータベース用コンテナの定義を記述して管理します。
![スクリーンショット 2021-08-29 12.12.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/e6da4a41-57d3-69a3-b370-4fb4a9f8ebe8.png)

ファイルを作成したら各々に定義を記述していきます。 ※ 各行で何をしているかはコメントを参照
■ Dockerfileの内容

```Dockerfile
#アプリ用コンテナの素

#ベースとなるバージョン2.6.5のrubyイメージを公式リポジトリより取得
FROM ruby:2.6.5

#RUNをbashで実行
SHELL ["/bin/bash", "-c"]

#各ソフトウェア(yarn,nodejs,npm,mysql,vim,nodeバージョン管理ライブラリ)をインストール。
#イメージ軽量化のためにapt-getリストをクリア

RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn nodejs npm default-mysql-client vim && \
npm install n -g && \
n 12.13.0 && \
echo "export PATH=/usr/local/n/versions/node/12.13.0/bin/:$PATH" >> ~/.bashrc && \ 
source ~/.bashrc && \ 
rm -rf /var/lib/apt/lists/*

#結合テスト(Rspec)用にChrome関連のインストール
RUN apt-get update && apt-get install -y unzip && \
    CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` && \
    wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/ && \
    unzip ~/chromedriver_linux64.zip -d ~/ && \
    rm ~/chromedriver_linux64.zip && \
    chown root:root ~/chromedriver && \
    chmod 755 ~/chromedriver && \
    mv ~/chromedriver /usr/bin/chromedriver && \
    sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -' && \
    sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' && \
    apt-get update && apt-get install -y google-chrome-stable

#アプリ用ディレクトリの作成 ※「memory_tank」の部分は適宜、自分のアプリ名にする
RUN mkdir /memory_tank

#ワークディレクトリを設定 ※「memory_tank」の部分は適宜、自分のアプリ名にする
WORKDIR /memory_tank

#ローカルのGemfileをアプリ用コンテナにコピーする
COPY Gemfile /memory_tank/Gemfile
COPY Gemfile.lock /memory_tank/Gemfile.lock

#アプリ用コンテナにgemをインストール
RUN gem install bundler
RUN bundle install
#結合テスト(Rspec)用にcapybara,selenium-webdriverを最新化
RUN bundle update capybara selenium-webdriver

#ローカルのアプリファイルをまるっとアプリ用コンテナにコピー
COPY . /memory_tank

 
```

■ docker-compose.ymlの内容

```docker-compose.yml
version: "2"
services:
  db: #データベース用コンテナの定義
    image: mysql:5.6 #ベースとなるバージョン5,6のmysqlイメージを公式リポジトリより取得
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci #文字コードの設定
    environment:
      MYSQL_ROOT_PASSWORD: xxxxxxxx #データベースユーザ「root」のパスワード
      MYSQL_DATABASE: memory_tank_development #データベース名
    volumes:
      - mysql-data:/var/lib/mysql #名前付きボリュームでデータを永続化 ※ Dockerの管理下にデータを保管
    ports:
      - "4306:3306" #ポート設定

  app: #アプリ用コンテナの定義
    build: . #DockerFileを素にコンテナイメージを作成
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" #Railsの起動

    volumes:
      - .:/memory_tank #ローカルのディレクトリをコンテナにマウント
    ports:
      - "3000:3000" #ポート設定
    depends_on: #作成順序の設定 「db」→「app」
      - db

volumes:
  mysql-data: #名前付きボリューム
```
#アプリ用コンテナとデータベース用コンテナの接続設定

次にアプリ用コンテナとデータベース用コンテナが正常に通信できるよう、「database.yml」を編集します。
※ socket通信でのDB接続ではなく「host：db」のように、データベース用コンテナを直接指定します。

```database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:*****
  host: db   #データベース用コンテナを指定
```

#コンテナ起動

ここまでで各種定義が完了したため、最後にコンテナをバックグラウンドで起動して稼働確認を行います。

```bash
xxxx@xxxxnoMacBook-Pro memory_tank % docker-compose up -d
Starting memory_tank_db_1 ... done
Starting memory_tank_app_1 ... done
xxxx@xxxxnoMacBook-Pro memory_tank % docker-compose exec app bin/rails db:migrate #マイグレーション
・・・
xxxx@xxxxnoMacBook-Pro memory_tank % docker-compose exec app bin/rails webpacker:install #webpackerのインストール
```
「localhost:3000」でアプリに接続できることを確認
![スクリーンショット 2021-08-29 13.39.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067765/09dac50f-fc3e-f466-bf48-a77dd0c1353d.png)

#まとめ
今回の作業を通し、ある程度はDockerについての基礎知識が身についてきたため、今後はwebアプリ初期段階でのDocker導入やAWS ECSへの本番デプロイに繋げていけたらと思います。

以上、最後まで読んで頂きありがとうございました！