はじめに
はい、標題の通りですが、DockerとCircleCIを使ってRailsアプリの自動テスト&自動Herokuへのデプロイ環境のテンプレートを作成しました。
どういうものか
Heroku用のDockerizedされたRailsアプリのテンプレートです。
docker-compse up
して rails new
してアプリを書いた後に、GitHubにpushすると自動テスト(RSpec)が実行されて、テストがすべて通るとHerokuへと自動デプロイされます。
- ローカル環境
- テスト実行
- デプロイ実行
- GitHubにpushして上記のテストが全て通るとCircleCIを通じてHerokuへとデプロイされる
- Heroku
なぜ作ったか
ギョームだと、ローカルはVagrantでProductionやStagingはAWSであることが多いのですが、個人開発でいちいちVagrantに環境を整えるは面倒だし本番も雑にHerokuでいいやと思ったので、Docker+HerokuのRailsアプリのテンプレートを作成しました。加えて、楽したいからGitHubにpushしたら自動テストと自動デプロイが走るようにCircleCIの設定を整えました。
作成物
作成物は下記になります。
github.com
続けて、DockerとCirclrCIの設定を見ていきます。
Dockerfile
FROM ruby:2.5.1
ENV LANG C.UTF-8
RUN apt-get update -qq && \
apt-get install -y build-essential \
apt-transport-https \
libpq-dev \
postgresql-client \
--no-install-recommends
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - \
&& apt-get install -y nodejs
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 && apt-get install -y yarn
RUN mkdir /rails_app
WORKDIR /rails_app
COPY Gemfile /rails_app/Gemfile
COPY Gemfile.lock /rails_app/Gemfile.lock
COPY yarn.lock /rails_app/yarn.lock
RUN bundle install --jobs=4 --no-cache
COPY . /rails_app
EXPOSE 3000
RUN RAILS_ENV=production rails assets:precompile
CMD ["rails", "s", "-b", "0.0.0.0"]
Rails用のよく見る形のDockerfileだと思います。
必要なパッケージをインストールして、bundle installして、そして最後にアプリ全体をコピーしています。
rails s
する直前で assets:precompile
を実行しています。
docker-compose.yml
version: '3'
services:
web:
build:
context: .
tty: true
stdin_open: true
ports:
- '3000:3000'
volumes:
- .:/rails_app
depends_on:
- db
db:
image: postgres:10.3
ports:
- '5432:5432'
volumes:
- postgresql-data:/var/lib/postgresql/data
volumes:
postgresql-data:
driver: local
こちらもよく見るRails+PostgreSQLの構成のdocker-compose.ymlだと思います。
特記すべき点は、2点あって、
1点目が、Dockerコンテナ内でも binding.pry
でデバッグ可能にするために下記の設定を追加している点です。
web:
tty: true
stdin_open: true
binding.pry
を埋め込んで、 docker-compose run --rm --service-ports web
で起動すると他環境と同様にデバッグすることができます。
2点目が、DBのデータを永続化するために下記の設定を追加している点です。
db:
volumes:
- postgresql-data:/var/lib/postgresql/data
volumes:
postgresql-data:
driver: local
この設定を追加することによって、DBの中身をローカルに永続化でき docker-compose up
を止めてもDBの中身が消えません。
CircleCI2.0
.circleci/config.yml
version: 2
jobs:
test:
machine:
image: circleci/classic:edge
steps:
- checkout
- run:
name: docker-compose build
command: docker-compose build
- run:
name: docker-compose up
command: docker-compose up -d
- run:
name: sleep for waiting launch db
command: sleep 1
- run:
name: rails db:create and db:migrate
command: docker-compose run web rails db:create db:migrate
- run:
name: rspec
command: docker-compose run web rspec
- run:
name: docker-compose down
command: docker-compose down
deploy:
working_directory: ~/deploy
machine:
image: circleci/classic:edge
steps:
- checkout
- run:
name: Build docker image
command: docker build --rm=false -t registry.heroku.com/${HEROKU_APP_NAME}/web .
- run:
name: Setup Heroku command
command: bash .circleci/setup_heroku.sh
- run:
name: Execute Heroku maintenance on
command: heroku maintenance:on --app ${HEROKU_APP_NAME}
- run:
name: Push container to registry.heroku.com
command: |
docker login --username=_ --password=$HEROKU_AUTH_TOKEN registry.heroku.com
docker push registry.heroku.com/${HEROKU_APP_NAME}/web
- run:
name: Execute Heroku db migrate
command: heroku run rails db:migrate --app ${HEROKU_APP_NAME}
- run:
name: Execut Heroku maintenance off
command: heroku maintenance:off --app ${HEROKU_APP_NAME}
workflows:
version: 2
test-deploy:
jobs:
- test
- deploy:
requires:
- test
filters:
branches:
only: master
特記すべき点は、 test
job, deploy
job共に下記のように machine imageに ciecleci/classic:edge
を指定していること。
test:
machine:
image: circleci/classic:edge
このように設定することにより、最新のdocker-compseがインストール済みの仮想マシンを使うことができます(楽)
参考
circleci.com
.circleci/setup_heroku.sh
wget https://cli-assets.heroku.com/branches/stable/heroku-linux-amd64.tar.gz
sudo mkdir -p /usr/local/lib /usr/local/bin
sudo tar -xvzf heroku-linux-amd64.tar.gz -C /usr/local/lib
sudo ln -s /usr/local/lib/heroku/bin/heroku /usr/local/bin/heroku
cat > ~/.netrc << EOF
machine api.heroku.com
login $HEROKU_LOGIN
password $HEROKU_API_KEY
EOF
ssh-keyscan -H heroku.com >> ~/.ssh/known_hosts
CiecleCIのworkflowの deploy
jobで実行している setup_heroku.sh
は下記のリポジトリのスクリプトを参考(ほぼそのまま)にさせていただきましたm( )m
内容としては、herokuコマンドを使えるようにして、herokuのログイン設定を設定ファイルに追記して、SSHのknown_hostsを更新しています。
参考
github.com
まとめ
HerokuのRailsアプリ開発環境をDockerとCircleCIを使って作成しました。
Dockerを使うことによって、Rubyのインストールすらせずに素早くローカル開発環境を用意できるだけでなく、開発環境、テスト環境、本番環境で同じDockerイメージを使いまわせて環境の違いによる謎のバグに悩ませることなくRailsアプリの開発を行うことができます。便利ですね。
気が向いたら、このテンプレートを利用して具体的にHerokuでRailsアプリを動かすところを解説する記事を書きたいと思います。
参考
library/postgres - Docker Hub
https://hub.docker.com/_/postgres/
Heroku Container Registryで作るDocker時代のRails 5 入門 - Qiita
https://qiita.com/koduki/items/3aafc38c6c518bef2af3
docker-composeでRailsを開発しCircleCI 2.0でテストしてHerokuにdeployする - Qiita
https://qiita.com/Kesin11/items/47079bc7f659e71b694c
Choosing an Executor Type - CircleCI
https://circleci.com/docs/2.0/executor-types/
Kesin11/docker_rails_sample: Dockernized rails with CircleCI and Heroku
https://github.com/Kesin11/docker_rails_sample