LoginSignup
43
54

More than 3 years have passed since last update.

既存のRails6アプリをDocker化しつつCircleCIでシステムスペックも実行できる環境を作る

Last updated at Posted at 2020-01-29

以前にも似たような記事を書いたのですが、Rails6でCircleCIもかませたいとなると、色々と修正が必要だったので新しい記事として書きます。また今回の記事のサンプルプロジェクトはGithubで公開しています。

環境

  • Ruby 2.6.5
  • Rails 6.0.2.1

やりたいこと

  • Dockerを使って開発環境構築〜CircleCIでテスト実行
  • システムスペックもちゃんと動くようにしたい

Dockerfile

既存アプリケーションのルートディレクトリにDockerfileを作成します。基本的には公式ドキュメントなのですが、以下の2点追記が必要です。

  • yarn, chromium-driverインストールを追記
  • gem install bundlerを追記
FROM ruby:2.6.3
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn chromium-driver # yarnとchromium-driverを追記
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN gem install bundler # 追記
RUN bundle install
COPY . /myapp
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]

docker-compose.yml

こちらも公式とほぼ変わりありません。変更箇所としてはデバッグができるように、stdin_oepnttyの設定を追記し、標準入出力をアタッチしていることと、システムスペックを実行できるようSeleniumのイメージも取得していることです。

version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
      - chrome
    stdin_open: true
    tty: true
  chrome:
    image: selenium/standalone-chrome:3.141.59-dubnium
    ports:
      - 4444:4444

加えてserver.pidが存在することでサーバーを立ち上げられない」という事象を避けるため、entrypoint.shを追加します。これは公式ドキュメントと同じものです。


#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

docker-compose build

$ docker-compose build

既存のアプリケーションだとファイルが色々増えてしまっているので、コンテナが重くなりビルドに異常な時間がかかる場合があります。.dockerignoreを使用して、必要のないファイルは含めないようにすると、ビルドできると思います。

database.ymlを修正 & マイグレーション実行

RailsアプリケーションではデフォルトでlocalhostでDBが起動していることを期待していますが、Docker環境で利用するためにDBコンテナの情報を記述する必要があります。

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password:
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test
$ docker-compose up
$ docker-compose run web rake db:create 

システムスペック環境整備

Gemfile
group :test do
  gem 'capybara', '>=2.15'
  gem 'selenium-webdriver'
  gem 'webdriver'
  gem 'rspec-rails', '~>3.8' #追加
end
rails_helper.rb
require 'capybara/rspec'
Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

RSpec.configure do |config|
  # 省略
  # Setup to run system spec
  config.before(:each, type: :system) do
    driven_by :selenium_chrome
  end

  config.before(:each, type: :system, js: true) do
    driven_by :selenium_chrome
  end
end
spec/support/capybara.rb
Capybara.default_driver    = :selenium_chrome
Capybara.javascript_driver = :selenium_chrome

Capybara.register_driver :selenium_chrome do |app|
  options = ::Selenium::WebDriver::Chrome::Options.new

  options.add_argument('--headless')
  options.add_argument('--no-sandbox')
  options.add_argument('--disable-gpu')
  options.add_argument('--window-size=1400,1400')

  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

CircleCI設定ファイル

続いてCircleCIの設定までやってしまいます。
上記の設定でdatabase.ymlも書き換えているので、CIの設定ファイルも修正が必要になります。

  • DATABASE_URLを設定しないとcould not translate host name "db" to addresで弾かれる
  • bundle exec bin/webpackの実行しないと、Webpacker can't find application...のエラーで弾かれる
.circleci/config.yml
version: 2
jobs:
  build:
    working_directory: ~/my-app
    docker:
      - image: circleci/ruby:2.6.3-node-browsers
        environment:
          BUNDLE_RETRY: 3
          BUNDLE_PATH: vendor/bundle
          DATABASE_URL: postgres://postgres:password@localhost:5432/myapp_test
          RAILS_ENV: test
      - image: circleci/postgres:11-alpine
    steps:
      - checkout
      - restore_cache:
          keys:
            - my-app-bundle-v1-{{ checksum "Gemfile.lock" }}
            - my-app-bundle-v1-
      - run:
          name: Bundlerをinstall
          command: |
            gem update --system
            gem install bundler
      - run:
          name: Bundle Install
          command: bundle check || bundle install
      - save_cache:
          key: my-app-bundle-v1-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle
      - restore_cache:
          keys:
            - rails-demo-yarn-{{ checksum "yarn.lock" }}
            - rails-demo-yarn-
      - run:
          name: Yarnをinstall
          command: yarn install --cache-folder ~/.cache/yarn
      - run:
          name: Wait for DB
          command: dockerize -wait tcp://127.0.0.1:5432 -timeout 1m
      - run:
          name: Database setup
          command: bin/rails db:create db:schema:load --trace
      - run: bundle exec bin/webpack
      - run:
          name: execute rspec
          command: bundle exec rspec
      - store_test_results:
          path: /tmp/test-results

CircleCIはローカルでも実行できるので、便利ですよね。

# タイポチェック
$ circleci config validate .circleci/config.yml

# ローカルでジョブを実行
$ circleci local execute --job build

参考

43
54
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
43
54