DockerとCircleCIを使ってRailsアプリの自動テスト&自動Herokuへのデプロイ環境を作った
はじめに
はい、標題の通りですが、DockerとCircleCIを使ってRailsアプリの自動テスト&自動Herokuへのデプロイ環境のテンプレートを作成しました。
どういうものか
Heroku用のDockerizedされたRailsアプリのテンプレートです。
docker-compse up
して rails new
してアプリを書いた後に、GitHubにpushすると自動テスト(RSpec)が実行されて、テストがすべて通るとHerokuへと自動デプロイされます。
- ローカル環境
- DockerizedなRails+PostgreSQLで開発する
- テスト実行
- デプロイ実行
- GitHubにpushして上記のテストが全て通るとCircleCIを通じてHerokuへとデプロイされる
- Heroku
- ローカルと同じ構成の環境がデプロイされる
なぜ作ったか
ギョームだと、ローカルはVagrantでProductionやStagingはAWSであることが多いのですが、個人開発でいちいちVagrantに環境を整えるは面倒だし本番も雑にHerokuでいいやと思ったので、Docker+HerokuのRailsアプリのテンプレートを作成しました。加えて、楽したいからGitHubにpushしたら自動テストと自動デプロイが走るようにCircleCIの設定を整えました。
作成物
作成物は下記になります。
続けて、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 # node RUN curl -sL https://deb.nodesource.com/setup_6.x | bash - \ && apt-get install -y nodejs # yarn 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/setup_heroku.sh
#!/bin/bash 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 # Add heroku.com to the list of known hosts ssh-keyscan -H heroku.com >> ~/.ssh/known_hosts
CiecleCIのworkflowの deploy
jobで実行している setup_heroku.sh
は下記のリポジトリのスクリプトを参考(ほぼそのまま)にさせていただきましたm( )m
内容としては、herokuコマンドを使えるようにして、herokuのログイン設定を設定ファイルに追記して、SSHのknown_hostsを更新しています。
参考
まとめ
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