AWS EC2 上に Rails の開発環境を構築する

Rails アプリの開発環境じゃなくて、 rails/rails にプルリクを送るための開発環境を作る方法です。

rails-dev-box について

Rails には Contributing to Ruby on Rails guide というドキュメントがあり、 誰でも簡単に開発環境を作ることができます。

5.1.1 The Easy Way

The easiest and recommended way to get a development environment ready to hack is to use the rails-dev-box.

「The Easy Way」の名前通り、 vagrant up するだけで簡単に開発環境が構築できてしまいます。

問題点

私の使っている PC は MacBook なので、ちょっと VagrantRails を動かすのはスペック的にツラいです。そこで、AWS EC2 上に開発環境を構築してみました。

Vagrant + Ansible

開発環境は Vagrant(+vagrantup-aws) と Ansible を使いました。

$ vagrant up --provider=aws
$ vagrant ssh
ubuntu@xxx: ~$ cd ~/src/rails
ubuntu@xxx: ~$ bundle exec rake
...

のような感じで AWS EC2 にお金さえ払えば、誰でも簡単に Rails の開発環境が使えるようになります。

Vagrantfile と playbook.yml は以下の通りです。*1

Vagrantfile

# frozen_string_literal: true

Vagrant.configure("2") do |config|
  config.vm.box = "dummy"

  config.vm.provider :aws do |aws, override|
    aws.access_key_id = ENV["AWS_ACCESS_KEY_ID"]
    aws.secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"]
    aws.region = ENV["AWS_DEFAULT_REGION"]

    # Ubuntu Server 16.04 LTS (HVM), SSD Volume Type
    aws.ami = "ami-48630c2e"

    # m3.medium  $0.096 / hour
    # m3.large   $0.193 / hour
    # m3.xlarge  $0.385 / hour
    # m3.2xlarge $0.77  / hour
    aws.instance_type = "m3.large"

    aws.keypair_name = ENV["AWS_KEYPAIR_NAME"]
    aws.security_groups = ["rails-dev"]
    aws.tags = { Name: "rails-dev" }

    override.ssh.username = "ubuntu"
    override.ssh.private_key_path = "~/.ssh/#{ENV["AWS_KEYPAIR_NAME"]}.pem"
  end

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
  end
end

playbook.yml

- name: rails
  hosts: all
  gather_facts: no

  vars:
    bootstrap_path: /tmp/bootstrap.sh
    rails_path: ~/src/rails

  pre_tasks:
    - name: install python-simplejson
      raw: sudo apt-get -y install python-simplejson
      register: output
      changed_when: output.stdout.find("1 newly installed") != -1

  tasks:
    - name: Download bootstrap.sh
      get_url:
        url: https://raw.githubusercontent.com/rails/rails-dev-box/master/bootstrap.sh
        dest: "{{ bootstrap_path }}"

    - name: Replace user from vagrant to ubuntu
      replace:
        path: "{{ bootstrap_path }}"
        regexp: "vagrant"
        replace: "ubuntu"

    - name: Install packages
      become: yes
      apt:
        name: "{{ item }}"
      with_items:
        - libreadline-dev

    - command: which ruby
      register: which_ruby
      failed_when: which_ruby.rc not in [0, 1]
      changed_when: no

    - name: Bootstrap for Rails
      become: yes
      command: "bash {{ bootstrap_path }}"
      when: which_ruby.rc == 1

    - name: git clone rails/rails
      git:
        repo: "https://github.com/rails/rails.git"
        dest: "{{ rails_path }}"

    - name: bundle install
      bundler:
        chdir: "{{ rails_path }}"
        extra_args: "--jobs=4"

注意点

  • Ubuntu 16.04 だと Python 3 とかの問題で pre_tasks 無いと動かない。よく分かっていない
  • aws.security_groups は group ID じゃなくて、 Name を使う必要がある。

  • ActiveStorage のテストは一部テストが落ちる。

ActiveStorage のテスト

このブログ読んで、ImageMagick に詳しい人いたらコメントやプルリクを頂けると凄く助かります。

ubuntu: ~/src/rails/activestorage $ bundle exec rake
...
(中略)
Error:
ActiveStorage::Previewer::PDFPreviewerTest#test_previewing_a_PDF_document:
MiniMagick::Invalid: `identify /tmp/mini_magick20180306-5674-pg12ad` failed with error:
identify: no decode delegate for this image format `' @ error/constitute.c/ReadImage/501.

みたいなのでテスト落ちて、よく分からなかった。

まとめ

AWS EC2 を使うことで、Rails の全件テストを 80 円/1 時間 で実行できるようになりました。

あとは Rails に送るパッチを完成させて、英語のコミットログを用意するだけです!*2

*1:実際のファイルは sinsoku/dotfiles に置いてあります

*2:Ruby より英語の方が圧倒的に大変