tl;dr
- タイトルの「私」は関係ありません。語感だけです。
- 主にDockerを用いた開発環境の話。
- Docker使って開発するとメリットも大きいけど、ハマりどころもあるし、デメリットもある。
- 目的を見極めて適切に使いましょう。
who am i
- github/bananaumai
- twitter/banana_umai
- Working at Livesense, inc as SRE
背景 - 運用状況
- 転職会議で部分的に本番導入中(順次移行中)。
- Amazon ECSを利用中。
- サービス開発に関わる、チームの規模が大きくなってきて、それとあわせて、サービスもマイクロに分割し始めていた。
背景 - 開発現場の課題感とDocker化
以下、自分の所属する開発チームでの課題感とそれに対してのDocker化によって(想定している)メリット感です。
- 課題感
- サービスはAWS EC2上で構築しているが、サーバーの管理をサービス開発に携わるアプリケーション開発者でセルフサービス化していくのにはハードルが高かった。
- 複数のプロジェクトを触るので、普段開発していないがたまに触るサービスなどがあった時にローカルの開発環境のセットアップのための手間が大きい。
- Docker化によるメリット
- EC2ベースに比べてアプリケーションサーバーの構築/管理がDockerのほうが容易で、セルフサービスしやすい。
- 開発環境の差異を相対的に受けづらく、開発環境の構築が相対的に容易。
開発環境関連のTIPS
- 以下はdocker-composeを使ってローカル開発を行っていくという前提としています。
- Railsアプリケーションはdocker-compose上でrailsというサービスで設定。
- また、Docker Container上は
/rails
ディレクトリ上にアプリケーション構築。
version: '2'
services:
web:
build: .
command: bin/rails s
environment:
volumes:
- .:/rails
links:
- db
ports:
- "3000:3000"
stdin_open: true
tty: true
db:
snip...
gemの管理(1)
Docker公式のQuickstartではGemfileの追加時に bundle install
が使われているが、 bundle lock
の方が良い。
$ edit Gemfile
$ docker-compose run rails bundle lock
$ docker-compose build # この中でbundle installを走らせる
gemの管理(2)
- gemは$GEM_HOMEにおいたほうが良い (
{Rails.root}/vendor/bundle
は避ける) - Rails.rootをDockerコンテナとマウントする際に、Gemfileの更新がうまくいかない。
- 以下のようにignore的にAnonymous Volumeを使っていたことがあるが、トラブルの原因になりがち。
version: '2'
services:
rails:
# snip
volumes:
- .:/rails
- /rails/vendor # <- トラブルの元
※ IDEを使っている際に、vendorファイルがないとコード補完等で不便だったりしますが、RubyMineではRemote Ruby Interpereter Integrationを使えば解決します。
Debugger(1) - byebug / pry-byebugを使う
明示的に、docker実行時に仮想端末モードを有効にし、標準入力をオープンしておく必要がある。
version: '2'
services:
rails:
# snip
stdin_open: true
tty: true
Debugger(2) - ruby-debug-ideを使ってIDEでデバッグ
以下RubyMineでの設定例ですが、他のIDEも同じような感じだと思います。
その上で以下の形でコマンドを実行(bundlerでインストールした場合)。
$ docker-compose run -p 1234:1234 -p 3000:3000 rails bundle exec rdebug-ide --host 0.0.0.0 --port 1234 --dispatcher-port 26162 -- $COMMAND$
Debugger(3) - byebugとruby-debug-ide両方を使う場合(問題)
- 現場では開発環境が自由であり、かつ、多人数で開発している。
- 使っているdebuggerが異なる。
- Mac等のホストOS上ではうまく動作しますが、Dockerコンテナ上でデバッグしようとした場合に、お互いのGemが競合してしまい、どちらも正常に動作しません。
...
byebug (9.0.6)
...
pry-byebug (3.4.3)
...
ruby-debug-ide (0.6.0)
Debugger(4) - byebugとruby-debug-ide両方を使う場合(回避方法)
Gemfileでデフォルトでrequireされないようにした上で、initializerの中で環境変数を見てDebuggerを振り分ける。
group :development, :test do
gem 'pry-byebug', require: false
gem 'pry-rails', require: false
gem 'ruby-debug-ide', require: false
gem 'debase', require: false
end
if Rails.env == 'development'
if ENV.has_key?('ENABLE_REMOTE_DEBUG')
require 'ruby-debug-ide'
require 'debase'
Rails.logger.info "loaded: ruby-debug-ide"
else
require 'pry-rails'
require 'pry-byebug'
Rails.logger.info "loaded: pry-byebug"
end
end
上記の場合、ENABLE_REMOTE_DEBUG環境変数が有効な場合にのみ、IDE Remote Debugを有効にしているので、以下のように実行。
$ docker-compose run -p 1234:1234 -p 3000:3000 -e ENABLE_REMOTE_DEBUG=true rails bundle exec rdebug-ide --host 0.0.0.0 --port 1234 --dispatcher-port 26162 -- $COMMAND$
秘密情報の扱い
- RoR5.1以上の場合
- EncryptedSecretを使う。
- けど、Docker上にVim等のEditorがいないと動かないのは残念。
- RoR5.0以下の場合
アプリケーション実行 / テスト実行
$ docker-compose (up|run|exec)
特段なにってことはないのですが、やはりローカルマシンで実行するのは遅い。特にテスト等では顕著に差が出る気がする。
CI
- CircleCI上でDocker on Dockerでbuild、テストを行っているが、やはりオーバーヘッドが大きくて遅いのが課題になっている。
- CircleCI2.0で任意のDocker Repositoryを指定できるので、そうしていきたい (<- まだやってない)
所感
- ローカルで開発する上では様々なオーバーヘッドがある。
- 例えば、少人数でスタートアップする際にHerokuとかでシンプルなアプリケーションを組めるならば、Dockerとか使わなくても良いような気がしてたりします。
- なので、実際に解決したい問題が明確にマッチするかという意識は持ったほうが良さそう。
- 自分の所属するチームでは冒頭にあげたような課題感があったが、改善を感じる。