Adways Advent Calendar 11日目の記事です。
http://blog.engineer.adways.net/entry/advent_calendar/archive
こんにちは、清水です。
普段はRailsでサービス開発を行っているエンジニアです。
みなさん普段の開発環境はどうなっているでしょうか?
AWS??ローカルにVM??Docker??
最近関わるサービスについてはDockerで開発環境を構築するようにしています。
サービス開発で悩ましいのは本番とローカルの環境に差分があることだと思います。
解決方法はいろいろありますが、出来れば大きな変更は入れずに切り分けたいです...
さて、サービスの本番環境はAWSが多いですが、各サービスと開発環境でのマッピングを考えると...
サービス | 本番環境(AWS) | 開発環境(Docker) |
---|---|---|
データストア | RDS | MySQL |
キャッシュ | ElastiCache or EC2 | Redis |
Webサーバ | Nginx on EC2 | Nginx |
ストレージ | S3 | ??? |
ストレージ部分が ???
ですね。
アップロードされたファイルの扱いに困っていました。ローカルのストレージに入れるのもいいのですが、長らく自分の中でコレ!というものが決まっていませんでした。
そこで、使い始めたのがminioです。 Go製のオブジェクトストレージサーバです。
- S3互換(大事)
- 簡単に構築できる(大事)
- Web UI(うれしい)
Web UIは LIVE DEMO もあります。
S3互換のおかげで、Railsの画像アップロードによく使われる paperclip や carrierwave からも簡単に使うことができます。
Railsをサンプルに使ってみましょう。
docker-composeから一気に起動します。
# cat docker-compose.env ... snip MINIO_ACCESS_KEY=[access key を入れてください] MINIO_SECRET_KEY=[secret key をいれてください] # cat docker-compose.yml --- version: '2' services: datastore: build: containers/datastore container_name: minio-sample-container minio: build: context: . dockerfile: Dockerfile-minio ports: - '9000:9000' command: [server, /minio] volumes_from: - datastore env_file: - ./docker-compose.env mysql: image: mysql:5.6.35 command: mysqld --character-set-server=utf8 env_file: - ./docker-compose.env ports: - '3306:3306' volumes_from: - datastore rails: build: . depends_on: - minio - mysql ports: - '3000:3000' env_file: - ./docker-compose.env environment: RAILS_ENV: docker volumes: - .:/usr/src/app volumes_from: - datastore links: - minio - mysql # docker-compose up -d
dockerと通信できるIPにポート9000でアクセスすると
(minioにはCLIツールとして mc というものもあり、WebUIに頼らなくても操作できて便利です。)
bucketを作ったり、bucketへの権限を変更できます。Railsから参照するバケットの作成と参照権限を与えておきます(minio-sample としました)。
これで準備ができたので、それぞれの設定を追加していきます。
paperclip の場合
RAILS_ENV=docker
での起動時の設定を追加します。
# config/initializers/paperclip.rb PAPERCLIP_OPTS = case Rails.env when 'docker' { image: { styles: { original: '1920x1680>', }, storage: :s3, s3_protocol: :http, s3_region: 'us-east-1', # 固定 s3_credentials: "#{Rails.root}/config/s3.yml", s3_host_name: 'localhost:9000', # 環境に合わせて変更します s3_options: { endpoint: 'http://minio:9000', force_path_style: true, }, path: ":attachment/:id/:style.:extension", url: ':s3_path_url', } } else # 他の環境の分をここに end
モデル側は
has_attached_file :image, PAPERCLIP_OPTS[:iamge]
気をつける点として s3_options にある force_path_style
を忘れないようにします。
ファイルのPUT先のエンドポイントが
ttp://minio-sample.minio:9000 -> ttp://minio:9000/minio-sample
に変わります。
carrierwave の場合
# config/initializers/carrierwave.rb CarrierWave.configure do |config| case Rails.env when 'docker' config.fog_credentials = { provider: 'AWS', aws_access_key_id: ENV['MINIO_ACCESS_KEY'], aws_secret_access_key: ENV['MINIO_SECRET_KEY'], region: 'us-east-1', endpoint: 'http://minio:9000', path_style: true, } config.asset_host = 'http://localhost:9000/minio-sample-carrierwave' config.fog_directory = 'minio-sample-carrierwave' else # 他の環境をここに end end
paperclipとほとんど同じ設定でいけます。
まとめ
minioのおかげで開発環境のほとんどをDockerの中に閉じ込めることができました。
データはdockerのコンテナに閉じ込めているので、worktreeが違う場所でも同様のデータが参照できるようになったのでとても便利です。
上記の設定を入れたリポジトリが こちら になります。
(アップロードする画面も作っていません...)
(docker-for-macを使用して作成しているので、hostなどは適宜変更してください)
次は本間さんの記事です。