Alpine Linuxで素のRailsが動くDockerfile を作った

DBはPostgreSQLで、他に余分なgemを入れなければこんな感じ

FROM ruby:2.5.0-alpine

COPY Gemfile* /myapp/
WORKDIR /myapp

RUN apk upgrade --no-cache && \
    apk add --update --no-cache \
      postgresql-client \
      nodejs \
      tzdata && \
    apk add --update --no-cache --virtual=build-dependencies \
      build-base \
      curl-dev \
      linux-headers \
      libxml2-dev \
      libxslt-dev \
      postgresql-dev \
      ruby-dev \
      yaml-dev \
      zlib-dev && \
    gem install bundler && \
    bundle install -j4 && \
    apk del build-dependencies

COPY . /myapp

ポイント

  • --virtual を使うことで、bundle install にしか必要のないLibraryは、あとでまとめて削除してサイズを節約(100MBくらい違う)
  • gem install bundler は、ruby:2.5.0-alpine の中でもやっているけど、もっかい実行して最新のものを取得している

Alpine Linux とは?

組み込み用の超軽量ディストリビューション BusyBox をベースに、パッケージ管理ツール等をのせたものらしい

何が良いの?

Imageのサイズが軽い。とにかく軽い。単品のImageが5MBとか。

Imageが軽いと何が良いの?

生産性があがる

  • CIやデプロイ、開発環境作成時等、Imageをデプロイするタイミングでの待ち時間が減る
  • Imageのダウンロード/アップロードも待ち時間が減る

実際どのくらい違うの?

ruby 2.4.2 alpine と、ruby 2.4.2 でこれくらい違う

REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
ruby                  2.4.2-alpine        3bc1f3c1b02b        3 months ago        63.4MB
ruby                  2.4.2               5dce8a4be4f6        3 months ago        687MB

時代は alpine なの?

Docker公式のImageも Alpine Linuxだし割りとそんな感じ

ただ、コマンドも最低限だし、gemのインストールに必要なパッケージも色々手で入れる必要があるので、Dockerがあんまりわかんないうちは使わないほうが良いかも

おまけ

docker-compose.yml はこんな感じ

version: '3'
services:
  db:
    image: postgres:10-alpine
    volumes:
      - db_data:/var/lib/postgresql/data
  web:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/myapp:cached
      - bundle_data:/usr/local/bundle
    ports:
      - "3000:3000"
    depends_on:
      - db

volumes:
  db_data:
  bundle_data: