どうも、バックエンドエンジニアのサトウリョウスケです ✌︎('ω')✌︎
前回の記事では Docker を使って Rails 5.2 の環境構築をしました。 現在も引き続き Docker についてのお話をします。
その後も幾つか手を加え続けておりまして、現在この記事を書いている時点で v1.3.0
になりました 🎉
明らかに初回のナンバリングを間違えていた感がありますが、少しずつインクリメントさせていく楽しみを実感できて良いです 笑
前回からの変更点について
さて、前回の記事は v1.0.0
時点のものでしたが、ここで v1.3.0
になった現在の Dockerfile
を見てみましょう。
# Dockerfile FROM ryz310/rails-on-docker
なんと!たったの1行ぽっちです!\\\٩( 'ω' )و ////
何言ってんだコイツと思われそうですが、これはどういう事かというと、大部分を base/Dockerfile
に移動したためです。
# base/Dockerfile FROM ruby:2.5 MAINTAINER ryz310@gmail.com RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs WORKDIR /myapp ENV BUNDLE_JOBS=32 ONBUILD ADD Gemfile /myapp/Gemfile ONBUILD ADD Gemfile.lock /myapp/Gemfile.lock ONBUILD RUN bundle install ONBUILD ADD . /myapp
この base/Dockerfile
のイメージは 僕のDocker Hub に置いてあります。
ONBUILD
が付いたコマンドはこのイメージを継承したイメージで実行されるため、先ほどの Dockerfile
には FROM
しかありませんが、ビルドの際には以下の 4 つのコマンドが実行される事になります。
ADD Gemfile /myapp/Gemfile ADD Gemfile.lock /myapp/Gemfile.lock RUN bundle install ADD . /myapp
感覚としては、 base/Dockerfile
で Rails の起動に必要なサーバー環境を構築して、 Dockerfile
で Rails そのものを構築していくような感じです。
Rails の構築には RDS イメージなども必須となってきますので、それについては docker-compose.yml
と組み合わせて構築していきます。
# docker-compose.yml version: '3' services: db: image: mysql:5.7 volumes: - mysql_data:/var/lib/mysql environment: MYSQL_ALLOW_EMPTY_PASSWORD: 'yes' ports: - "3306:3306" web: build: . image: web_image command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - .:/myapp - bundle:/usr/local/bundle ports: - "3000:3000" depends_on: - db environment: DB_HOST: db spring: image: web_image command: bundle exec spring server volumes: - .:/myapp - bundle:/usr/local/bundle tty: false stdin_open: false environment: DB_HOST: db volumes: mysql_data: bundle:
ここも v1.0.0
の頃からいくつか変更がありまして、例えば web
と spring
で同じ内容になるように v1.0.0
では YAML のエイリアスを使っていたのですが、 docker image で共有する方法に変えました。この定義の記述について少し補足します。
web
の定義で build: .
と image: web_image
と言う記述がありますが、これは Dockerfile をビルドして web_image
というタグをつける、と言う振る舞いになります。一方、 spring
の定義の image: web_image
では web_image
というタグが付いたイメージを使用する、という振る舞いになります。この辺はなんだかややこしいですね 😓
また、 bundle:/usr/local/bundle
を volume に指定する事で、bundle install
の内容を永続化するようにしてあります。これにより、$ docker-compose run --rm web bundle install
というコマンドが有効になってくるので、Gemfile を更新した際に一から Build する必要がなくなります。
同様に、 MySQL も mysql_data:/var/lib/mysql
を volume に指定する事で、テーブルの内容を永続化するようにしています。
まとめ
ONBUILD
を使用する事で、他の Rails アプリでも同じイメージを転用できるようになったのが一番の改善点ではないかと思います。
ただ、Rails アプリ側の事情で何か $ apt-get install
を加えたくなった場合にどうするのか、という課題感があります。base/Dockerfile
は汎用的な環境構築を意識しているので、あまり一般的でないインストールは行いたくありません。理想としては「子イメージ」で $ apt-get install
させて、「孫イメージ」で今回のように Rails の構築をする構成が実現できれば良いのではないかと思いますが、 ONBUILD
を「子イメージ」でスキップさせるとか出来るんでしょうか?
次回はこの辺について少し調べていければ、と思っています。