以前にも似たような記事を書いたのですが、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_oepn
とtty
の設定を追記し、標準入出力をアタッチしていることと、システムスペックを実行できるよう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
システムスペック環境整備
group :test do
gem 'capybara', '>=2.15'
gem 'selenium-webdriver'
gem 'webdriver'
gem 'rspec-rails', '~>3.8' #追加
end
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
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...
のエラーで弾かれる
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