logo logo

April 08, 2019 02:18

既存railsプロジェクトのdocker運用開始時の作業録

やったこと

既存のrailsアプリ開発環境をdockerで一括準備してみた。

  • OS: ubuntu16.04 LTS
  • DB in development: sqlite3
  • ruby: 2.5.3
  • rails: 5.1.7

個人の開発用の作業録につき、細かなGemfileの中身やバージョンなどは割愛します。
それらの依存関係によって正常動作しない可能性があります。

Dockerfile

アプリケーションのルート直下に以下のDockerfileを作成。

既存のruby:2.5.3というベースイメージを拡張する。

FROM ruby:2.5.3
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - \
        && apt-get install -y nodejs
RUN apt-get update -qq && apt-get install -y \
    build-essential \
 && rm -rf /var/lib/apt/lists/*
RUN mkdir /workdir
WORKDIR /workdir
ADD Gemfile /workdir/Gemfile
ADD Gemfile.lock /workdir/Gemfile.lock
RUN gem install bundler -v 2.0.1
RUN bundle install
RUN apt update
RUN apt install -y graphviz
ADD . /workdir
  • 2行目でnode.jsのバージョンを更新している。これがなかったときに Autoprefixer doesn’t support Node v4.8.2. Update it. というエラーが出現したために修正したもの。
  • 途中のrm -rf /var/lib/apt/lists/*は余計なキャッシュを削除するためのコマンド。
  • bundlerのバージョンはdeploy環境のherokuのバージョンを見越して調整した。
  • graphvizのインストールはプロジェクト内でrails erdの実行をおこなうため。一般にはオプショナルといった感じ

docker-compose.yml

version: '3'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      RAILS_ENV: development
    ports:
      - '3000:3000'
    volumes:
      - .:/workdir
    tty: true
    stdin_open: true
    command: bundle exec rails s -p 3000 -b '0.0.0.0'

起動

以上の2つのファイルを作成したら、まずはアプリのルート直下で、以下コマンドにてイメージをビルド。

$ docker-compose build

次にコンテナーを起動。-dはバックグラウンド起動のためのオプションだが、何か問題が起こった時はこれを省くとログが見られてハッピーな場合がある。

$ docker-compose up -d

bashに潜ってコマンドを実行したい場合はdocker psなどでプロセスIDを参照し、

$ docker exec -it (docker container id) bash

で潜れる。既存のデータベースがあればbundle exec rake db:migrateでマイグレーションを実行する。(開発環境のDBはsqlite)

ブラウザでlocalhost:3000にアクセスし、正常にアプリが動作していれば成功。そうでなければエラーログを頼りに対応していく。

その他

A server is already running.

docker processをkillした場合、アプリケーションサーバーが正常にダウンしない場合がある。
このような場合、docker-compose upを行うとA server is already running.となってプロセスが起動できなくなってしまう。(ちなみにdocker-compose up -dだとログがでないので、気づきにくい)

この場合は以下のようにpidを削除すると正常に起動できるようになった。(sudo必要かも)

$ rm ./tmp/pids/server.pid

rails consoleの実行

おそらく多くの方は、containerに入ってrails cで立ち上げられるはずだが、自分はこれでハマった。

Could not find rake-12.3.2 in any of the sources
Run `bundle install` to install missing gems.

というエラーが出て、言われた通りbundle installを実行しても何も解決しない。
ローカル環境のvendor/bundleを削除したりしていたので、以下はかなり個人の操作過程依存であることに注意いただきたい。
自分は、.bundle/configファイルの中身を空にすることでrails cが通るようになった。

手元のローカル環境でbundle installする際に、通常はプロジェクトの立ち上げ時に

bundle install --path vendor/bundle (或いはvendor/cacheも多いだろう)

などとして、gemのインストール先を指定すると思う(自分もそうしたはずだがとっくに忘れていた。)
そうすることでプロジェクト専用のgem環境を構築することができる。
それと同時に先の.bundle/configファイルが自動生成され、

---
BUNDLE_PATH: "vendor/bundle"
BUNDLE_DISABLE_SHARED_GEMS: "true"

などといった中身になる。これによってプロジェクトのdefaultのgem管理環境の読込先が指定されるようだ。
自分はローカル開発環境→docker移行で、vendor/bundleを一度削除していたりした。
一方でいくらbundle installをしても上のdocker設定ではシステム直下にインストールされるため、
vendor/bundleを参照しても何もなく、上のエラーが生じるというのが顛末のようだった。

dockerの設定でgemのインストール先を変えても良いが、公式イメージなどでもシステム直下に配置している。(これは例えばgem environmentなどを実行すると確認できる)
これはdockerがone service per one containerを標準思想としているため、そうなっているのだろう。

サーバーログの確認

デバッグなどに便利なサーバーログは以下のように確認できる。
いくつか方法があるようだが、dockerの設定をいじらない方法で自分が確認できた方法だけ

  • containerのbashでlogフォルダに移動し、
$ tail -n 100 development.log

を実行。-n 100オプションはログの末尾n行を抽出なので適宜変更。

  • containerを立ち上げる際にdocker-compose upでもログを垂れ流し確認可能