#はじめに
RailsアプリをDocker上で構築し、CircleCIを用いて、RSpecによる自動テスト、またHerokuへの自動デプロイの仕組みを実現していく。
環境
- フレームワーク : Rails
- テストフレームワーク : RSpec
- データベース : MySQL
- コンテナ : Docker(Docker Compose)
- CI/CDツール : CircleCI
- サーバー : Heroku
前提
GitHub、Herokuに登録済み
Docker、Docker Composeをインストール済み
参考
山浦清透さんのDocker超入門講座 合併版 | ゼロから実践する4時間のフルコースという動画を参考にさせていただく。
#Docker環境でRailsアプリを作成
作業用ディレクトリを用意し、必要なファイルを作成する。
今回はqiita-railsというディレクトリ内で作業していく。
qiita-rails/
├ src/
└ Gemfile
├ docker-compose.yml
└ Dockerfile
source 'https://rubygems.org'
gem 'rails', '~> 6.1.4', '>= 6.1.4.1'
version: '3'
services:
db:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
volumes:
- ./src/db/mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- ./src:/app
ports:
- "3000:3000"
environment:
RAILS_ENV: development
depends_on:
- db
FROM ruby:2.7
RUN 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 -qq \
&& apt-get install -y nodejs yarn \
&& apt-get -y install imagemagick
WORKDIR /app
COPY ./src /app
RUN bundle config --local set path 'vendor/bundle' \
&& bundle install
作業用ディレクトリに移動後、Railsアプリを作成。
$ docker-compose run rails new . --force --database=mysql
Gemfileが更新されたのでコンテナのイメージをビルドし直す。
$ docker-compose build
database.ymlのdefaultのpasswordとhostを設定。
.
.
.
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: password
host: db
.
.
.
データベースを作成する。
$ docker-compose run web rails db:create
コンテナを起動する。
$ docker-compose up
ブラウザでlocalhost:3000を開き、以下の画面が表示されていれば成功。
#Herokuの設定
Heroku、Heroku Container Registryにログインし、アプリを作成。
$ heroku login
$ heroku container:login
$ heroku create qiita-rails
MySQL用のアドオンを追加する(Herokuにクレジットカードの登録が必要)。
$ heroku addons:create cleardb:ignite -a qiita-rails
database.ymlのproductionを設定する。
.
.
.
production:
<<: *default
database: <%= ENV['APP_DATABASE'] %>
username: <%= ENV['APP_DATABASE_USERNAME'] %>
password: <%= ENV['APP_DATABASE_PASSWORD'] %>
host: <%= ENV['APP_DATABASE_HOST'] %>
$ heroku config -a qiita-rails
でこれらの環境変数を確認し
$ heroku config:add
でそれぞれ設定していく。
作業用ディレクトリに、start.shを追加し、Dockerfileを編集する。
qiita-rails/
├ src/
├ docker-compose.yml
├ Dockerfile
└ start.sh
#!/bin/sh
if [ "${RAILS_ENV}" = "production" ]
then
bundle exec rails assets:precompile
fi
bundle exec rails s -p ${PORT:-3000} -b 0.0.0.0
FROM ruby:2.7
ENV RAILS_ENV=production
RUN 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 -qq \
&& apt-get install -y nodejs yarn \
&& apt-get -y install imagemagick
WORKDIR /app
COPY ./src /app
RUN bundle config --local set path 'vendor/bundle' \
&& bundle install
COPY start.sh /start.sh
RUN chmod 744 /start.sh
CMD ["sh", "/start.sh"]
Herokuに環境変数を追加する。
$ heroku config:add RAILS_SERVE_STATIC_FILES='true' -a qiita-rails
#CircleCIでCI/CDを構築
事前にGitHubにリポジトリを作成しておく。
GemfileにRSpecを追加する。
group :development, :test do
gem 'rspec-rails'
end
Gemfileが更新されたのでコンテナのイメージをビルドし直す。
$ docker-compose build
下記ののコマンドでwebコンテナの中に入り、bashが使えるようにるので、
$ docker-compose exec web bash
RSpecをインストールする。
$ rails generate rspec:install
作業用ディレクトリに、.circleciディレクトリ、config.ymlを追加する。
qiita-rails/
├ src/
├ docker-compose.yml
├ Dockerfile
├ start.sh
└ .circleci/
└ config.yml
version: 2.1
orbs:
ruby: circleci/ruby@1.1.2
heroku: circleci/heroku@1.2.3
jobs:
build:
docker:
- image: circleci/ruby:2.7
working_directory: ~/qiita-rails/src
steps:
- checkout:
path: ~/qiita-rails
- ruby/install-deps
test:
docker:
- image: circleci/ruby:2.7-node
- image: circleci/mysql:5.5
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: app_test
MYSQL_USER: root
environment:
BUNDLE_JOBS: "3"
BUNDLE_RETRY: "3"
APP_DATABASE_HOST: "127.0.0.1"
RAILS_ENV: test
working_directory: ~/qiita-rails/src
steps:
- checkout:
path: ~/qiita-rails
- ruby/install-deps
- run:
name: Database setup
command: bundle exec rails db:migrate
- run:
name: yarn Install
command: yarn install
- run:
name: webpack
command: bundle exec bin/webpack
- run:
name: Rspec
command: bundle exec rspec
deploy:
docker:
- image: circleci/ruby:2.7
steps:
- checkout
- setup_remote_docker:
version: 19.03.13
- heroku/install
- run:
name: heroku login
command: heroku container:login
- run:
name: push docker image
command: heroku container:push web -a $HEROKU_APP_NAME
- run:
name: release docker image
command: heroku container:release web -a $HEROKU_APP_NAME
- run:
name: database setup
command: heroku run bundle exec rake db:migrate RAILS_ENV=production -a $HEROKU_APP_NAME
workflows:
version: 2
build_test_and_deploy:
jobs:
- build
- test:
requires:
- build
- deploy:
requires:
- test
filters:
branches:
only: main
database.ymlのtestを設定する。
.
.
.
test:
<<: *default
database: app_test
host: <%= ENV.fetch('APP_DATABASE_HOST') { 'db' } %>
.
.
.
$ heroku config:add
でmaster.keyの値をHerokuの環境変数RAILS_MASTER_KEYとして追加する。
CicleCIのサイトにログイン後、Projects→qiita-rails→Project Settings→Environment Variables→Add Environment Variablesと進み、
- Name:HEROKU_APP_NAME, Value:qiita-rails
- Name:HEROKU_API_KEY, Value:(HerokuのサイトでAccount settingsから確認)
を追加する。
#最後に
これで、gitにpush後GitHub上でCreate pull requestを行うと自動でRSpecによるテストが開始し、それが成功するとMerge pull requestが押せるようになり、Merge pull requestを実行するとまた自動でRSpecによるテストが開始し、それが成功すると自動でHerokuにデプロイされるという仕組みを実現することができた。
いずれサーバー環境をHerokuからAWSに切り替えようと考えている。