docker-composeを便利にするツール「dip」を使ってみた

dipとは

dipは、Rails開発会社のEvil Martiansのメンバーが作った、docker-composeでの作業を能率的に行えるツールです。dipはDocker Interaction Processの略だそうです。

Rubyで書かれていますが、Rubyがなくても使えます。元々Rails向けに作られたツールのようですが、Evil MartiansのReactアプリにもdip.xmlがあることからわかるように、Railsに限らず一般のdocker-composeでも使えます。私の場合はローカル開発環境でのみ使っています。

Evil Martiansはdipの記事を書くと言ってましたが、未だに出ていないので自分で記事を書いてみました😆。

dipのREADMEにはシェルと統合してdipを省略する方法も書かれていますが、ちょいやりすぎ感あったので自分はやっていません。

必要なもの

  • Ruby 2.3以上(Rubyを使う場合)
  • Dockerとdocker-composeがインストールされていること
  • docker-compose.ymlファイル

インストール

以下のいずれかの方法でdipをインストールし、dip.ymlをdocker-compose.ymlと同じ階層に置きます。

1. homebrewでのインストール

brew tap bibendi/dip
brew install dip

2. gemコマンドでのインストール

gem install dip

3. コンパイル済みバイナリのインストール

curl -L https://github.com/bibendi/dip/releases/download/4.2.0/dip-`uname -s`-`uname -m` > /usr/local/bin/dip
chmod +x /usr/local/bin/dip

dip.ymlの設定

リポジトリにある以下のdip.ymlはEvil MartiansのRails案件に寄った設定なので、自分の用途に応じてカスタマイズが必要です。interaction:の下のサブコマンドを適宜カスタマイズします。

version: '4'

compose:
  files:
    - docker-compose.yml

interaction:
  bash:
    description: Open the app container bash shell
    service: app
    command: /bin/bash

  dev:
    service: app
    command: exit
    subcommands:
      console:
        description: Open the gem console
        command: ./bin/console
      clean:
        description: Clean dependencies
        command: rm -rf Gemfile.lock

  bundle:
    description: Run Bundler commands
    service: app
    command: bundle

  rspec:
    description: Run Rspec commands
    service: app
    command: bundle exec rspec

  rubocop:
    description: Run Rubocop commands
    service: app
    command: bundle exec rubocop

provision:
  - dip app clean
  - dip bundle install

なおprovision:というコマンドは固定されているらしく、他の名前にできませんでした。

自分のカスタマイズ例

これは以下の記事で自分が使ったdip.ymlです。

Rails 6のDocker開発環境構築をEvil Martians流にやってみた

dip bashdip rubocopは長いのでdip shdip copにしてみました。

なおtest:というサブコマンドは予約語なのか認識できなかったので、minitest:としました。

version: '4'

environment:
  RAILS_ENV: development

compose:
  files:
    - docker-compose.yml

interaction:
  sh:
    description: Open the app container bash shell
    service: backend
    command: /bin/bash
    compose_run_options: [no-deps]

  bundle:
    description: Run bundler command
    service: backend
    command: bundle
    compose_run_options: [no-deps]

  rake:
    description: Run rake command
    service: backend
    command: bundle exec rake

  rails:
    description: Run rails command
    service: backend
    command: bundle exec rails
    subcommands:
      s:
        description: Start rails server
        service: rails
        compose_run_options: [service-ports]

  yarn:
    description: Run yarn command
    service: backend
    command: yarn

  minitest:
    description: Run minitest
    service: backend
    environment:
      RAILS_ENV: test
    command: bundle exec rails test

  cop:
    description: Run rubocop
    service: backend
    default_args: -a
    command: bundle exec rubocop

  psql:
    description: Run psql console
    service: postgres
    command: psql -h postgres -U postgres -d postgres

  inspect_all:
    description: Run all checkers
    service: backend
    command: bundle exec license_finder
    command: bundle exec rails test
    command: bundle exec rails_best_practices .
    command: bundle exec bundle-audit
    command: bundle exec brakeman

provision:
  - dip compose down
  - dip compose up -d postgres
  - dip yarn install
  - dip sh -c "./bin/setup 2> /dev/null; exit 0"
  - dip sh -c ./bin/setup
  - dip sh -c "RAILS_ENV=test ./bin/setup"

使い方

dip.ymlのあるディレクトリでdip lsすると、dip.ymlで設定したサブコマンドの一覧が表示されます。dip helpとするとさらに詳しいヘルプが表示されます。

$ dip ls
sh           # Open the app container bash shell
bundle       # Run bundler command
rake         # Run rake command
rails        # Run rails command
rails s      # Start rails server
yarn         # Run yarn command
minitest     # Run minitest
cop          # Run rubocop
psql         # Run psql console
inspect_all  # Run all checkers

あとはdip サブコマンドを実行するだけです。

サブコマンドにはdip bundle installdip rails consoleのようにオプションも追加できます。

dip sshdip nginxなど凝った機能がいろいろあるようですが、その辺りはまだ追求していません。

dipの便利な点

Dockerが公式にこういうツールを出せばいいのにと思っちゃいました。

1. コンテナにログインせずに作業できる

bundle installrails dbconsoleyarn install --check-filesといった決まりきったコマンドを実行するのに、いちいちシェルでログインするのは面倒です。また、Dockerのシェルの安定性にもちょっと不安があります。

dipならdip bundle installdip rails dbconsoledip yarn install --check-filesで実行できます。

なおGemfileがない状態でのrails newはさすがにログインが必要でした。

2. コンテナの起動状態を気にしなくてよい

docker-composeでコンテナに入る場合、コンテナが起動していなければdocker-compose run app bash、コンテナが起動していればdocker-compose exec app bashとするなど、面倒な使い分けが必要になります。

そもそもdocker-composeというコマンドが長すぎですよね。自分はdcomというbashエイリアスを作っているほどです。

dipなら、たとえば自分の設定したdip shdip rails sはコンテナが起動していなくても使え、dipが終了すればコンテナも終了してくれます。コンテナの二重起動を気にしなくてよくなるのは本当にありがたいです😂。

その分起動は少々遅くはなると思います。

まあ自分は何か作業した後はdcom downを実行する癖が付いてしまいましたが。

3. 複数のサブコマンド実行が書きやすい

docker-composeの中でシェルコマンドを複数実行しようとすると、たとえば以下のように&&でつなげてbash -cで実行するというダルい書き方になってしまいます。

command: bash -c "elasticsearch -d && elasticsearch --http.port=9250"

コマンドを5つも6つもつなげると美しくありませんし、シェルスクリプトに追い出すのも何だか敗北感があります。

dipなら自分のサブコマンドにcommand:を複数書けます。ただしこの方法はドキュメントに見当たらないので、サポート外機能のつもりで使っています。

  inspect_all:
    description: Run all checkers
    service: backend
    command: bundle exec license_finder
    command: bundle exec rails test
    command: bundle exec rails_best_practices .
    command: bundle exec bundle-audit
    command: bundle exec brakeman

4. Dockerfileやdocker-compose.ymlの変更が基本的に不要

dip.ymlはDockerfileやdocker-compose.ymlと別に設定できるので、うかつにこれらを変更してチームの人に怒られずに済みます。dip.ymlを~/.gitignore_globalに加えておけば自分用に心ゆくまでカスタマイズできます。

試していませんが、さすがにsshログイン機能などを使う場合はdocker-compose.ymlの変更も必要そうです。

services:
  web:
    environment:
      - SSH_AUTH_SOCK=/ssh/auth/sock
    volumes:
      - ssh-data:/ssh:ro

volumes:
  ssh-data:
    external:
      name: ssh_data

おまけ

以下のprovision:コマンドは自分のRails開発環境の初期設定用にbin/setupなどを実行します。

provision:
  - dip compose down
  - dip compose up -d postgres
  - dip yarn install
  - dip sh -c "./bin/setup 2> /dev/null; exit 0"
  - dip sh -c ./bin/setup
  - dip sh -c "RAILS_ENV=test ./bin/setup"

4つ目のdip sh -c "./bin/setup 2> /dev/null; exit 0"は本来不要なはずなのですが、自分の環境ではなぜか./bin/setupが1回目で必ずデータベース接続に失敗し、2度目だと成功するので、仕方なく加えています😅。そのうち直したいです。

おたより発掘

関連記事

クジラに乗ったRuby: Evil Martians流Docker+Ruby/Rails開発環境構築(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

BPSアドベントカレンダー

週刊Railsウォッチ