kawabatas技術ブログ

試してみたことを書いていきます

Rails の Dockerfile の自分なりのベストプラクティス

概要

この度、Dockerfile, docker-compose.yml を見直してみました。

その際に調べたことのメモです。

試す、見直すこと

  • Dockerfile 見直し
  • ruby alpine イメージを試す
  • bundle config 周りの見直し
  • docker-compose で bundle を volume するか見直し

Dockerfile ベストプラクティス

https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ Dockerfileを書くときに気をつけていること10選

In Docker 1.10 and higher, only the instructions RUN, COPY, ADD create layers. Other instructions create temporary intermediate images, and do not directly increase the size of the build.
  • RUN, COPY, ADD はまとめる
Sort multi-line arguments
  • アルファベット順に
Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. 
  • COPY を使う

ruby alpine イメージを試す について

ruby alpine と google/protobuf の間でバグがあるようで、使用を見送りました。

https://github.com/google/protobuf/issues/4460

bundle config 周りについて

ruby の公式イメージは /usr/local/bundle です。

https://github.com/docker-library/ruby/blob/699a04311386ecc98ca242fc9bdee17fb4008863/2.5/stretch/Dockerfile

BUNDLE_PATH を vender/bundle などに変更すべきなのかわからず。。。container におけるベストプラクティスはどうなのだろう。

docker-compose で bundle を volume するか見直し

docker build は時間がかかるので、gem 更新時は docker-compose run app bundle install できた方がいいと感じました。

cached や delegated については遅く感じ始めたら対応する方針で良いかと。

https://docs.docker.com/compose/compose-file/#caching-options-for-volume-mounts-docker-for-mac

まとめ

一旦、こんな感じがベストなのかなと。

FROM ruby:2.5.1

ENV LANG C.UTF-8
ENV APP_HOME /home/app

WORKDIR $APP_HOME

COPY Gemfile* ./

RUN apt-get update -qq && apt-get install -y --no-install-recommends \
      build-essential \
      mysql-client \
    curl -sL https://deb.nodesource.com/setup_10.x | bash - && apt-get install -y nodejs && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    gem install bundler && \
    bundle install

COPY . .

EXPOSE 3000
CMD ["bundle", "exec", "rails", "server", "-p", "3000", "-b", "0.0.0.0"]
version: '3'
services:
  mysql:
    image: mysql:5.7.19
    environment:
      - MYSQL_ROOT_PASSWORD=root
    ports:
      - "3307:3306"
    volumes:
      - db-data:/var/lib/mysql
  app:
    build: .
    image: my-rails/app
    environment:
      RAILS_ENV: development
    volumes:
      - .:/home/app
      - bundle-data:/usr/local/bundle
    ports:
      - "3000:3000"
    depends_on:
      - mysql
volumes:
  bundle-data:
  db-data: