Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

Docker: Ubuntu12をベースイメージにしてRails環境をDockerで構築する

古い環境を構築する話です。
ニーズは狭いですが、刺さる人には刺さるだろうなと思って書いてみます。

筆者が作業していた環境のバージョンは以下のとおりですが、多少異なる場合でも同じように環境構築できると思います。

  • OS: Ubuntu 12.04
  • Ruby: 1.9.3
  • Rails: 3.2.18
  • OpenSSL: 1.0.1

成果物

早速ですが、自分が作成したファイルを紹介します。


Dockerfile(クリックで展開)
FROM ubuntu:12.04
ENV LANG C.UTF-8
ENV RUBY_MAJOR 1.9
ENV RUBY_VERSION 1.9.3-p194
# バージョン2.3未満のRubyに対してはBundler 1しか対応していない https://bundler.io/compatibility.html
ENV BUNDLER_VERSION 1.16.6

# OSが古いためaptリポジトリを変更する
# OSを archive.ubuntu.com が管理するバージョンまでアップグレードした場合、以下の行は削除してよい
RUN sed -i -e 's/archive.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list

# Rubyのインストールに必要なaptパッケージをインストールする
# 参考 https://hub.docker.com/layers/library/ruby/2.1-slim/images/sha256-610647397432a2b1762e29beaf4f4c723399204f1e111531a90bc50d98ca867e
RUN apt-get update && \
    apt-get install -y --no-install-recommends build-essential sudo \
    bzip2 ca-certificates libffi-dev libgdbm3 libssl-dev libyaml-dev procps zlib1g-dev \
    autoconf bison dpkg-dev gcc libbz2-dev libgdbm-dev libglib2.0-dev libncurses-dev libreadline-dev libxml2-dev libxslt-dev make ruby wget xz-utils

# gemのインストールに必要なaptパッケージをインストールする
# devise -> git(Gemfileでgitの指定あり)
# nokogiri -> pkg-config libxml2-dev libxslt-dev https://nokogiri.org/tutorials/installing_nokogiri.html#installing-using-standard-system-libraries
  # 後者二つはインストール済み
# pg -> libpq-dev
# mini_magick -> imagemagick
# rspec -> xvfb
RUN apt-get -y install git pkg-config libpq-dev imagemagick xvfb

# Rubyをインストールする
RUN wget https://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.gz &&  \
    tar xvf ruby-$RUBY_VERSION.tar.gz &&  \
    rm ruby-$RUBY_VERSION.tar.gz && \
    cd ruby-$RUBY_VERSION && \
    ./configure --build="$gnuArch" --disable-install-doc --enable-shared && \
    make -j "$(nproc)" && \
    make install && \
    cd .. && \
    rm -rf ruby-$RUBY_VERSION

ENV APP_HOME /rails
RUN mkdir $APP_HOME
WORKDIR $APP_HOME

# gemをインストールする
COPY Gemfile* $APP_HOME
RUN gem install bundler -v $BUNDLER_VERSION
# nokogiri同梱のパッケージを利用するとインストールがパスしないので、OSのパッケージを利用する https://nokogiri.org/tutorials/installing_nokogiri.html#installing-using-standard-system-libraries
RUN bundle config build.nokogiri --use-system-libraries
RUN bundle config set jobs $(nproc) && bundle install

ADD . $APP_HOME

# 作業用非rootユーザーを作成する
ARG UID
ARG GID
ARG USERNAME
RUN groupadd $USERNAME -g $GID -o && \
    useradd $USERNAME -u $UID -g $GID -o --create-home --shell /bin/bash
USER $USERNAME:$USERNAME

compose.yml(クリックで展開)
services:
  web:
    build:
      context: .
      args:
        UID: ${UID:-1000}
        GID: ${GID:-1000}
        USERNAME: ${USERNAME:-rails}
    ports:
      - 3000:3000
    command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    depends_on:
      - db
    tty: true
    stdin_open: true
    volumes:
      - .:/rails:cached
      - bundle_volume:/usr/local/bin:cached
  db:
    image: postgres:9.4
    ports:
      - 5432:5432
    volumes:
      - db_volume:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
volumes:
  bundle_volume:
  db_volume:

動機

なんでUbuntuをベースイメージにしているんだ、Rubyをベースイメージにすればいいじゃないか、と思う方もいるかもしれません。
これは、UbuntuとRubyでそれぞれバージョンを指定したいためです。

具体的には以下のような事情があり、ローカル環境でUbuntuとRubyを別々にアップグレードして動作確認できるようにしました。

  • Ubuntu、Ruby共に古い本番環境で、AWS S3 APIがTLS1.2以上を必須としたことに起因するエラーが発生していた
  • エラーを解消しようにもTLS ← OpenSSL ← Ubuntuのaptパッケージ ← Rubyというバージョン依存があり、アップグレード作業がRubyまで波及していきそうではないかと、事前調査によって見当がついた
  • 一方で、実際に着手すればディストリビューションのアップグレードだけで解決する可能性もあるため、個々のレイヤーで更新作業を実施しながらエラー解消に取り組みたかった

また、作業着手前には以下のような運用が行われており、開発環境構築について手入れしたかったというのが、Docker化のモチベーションになっています。

  • ローカル開発環境の構築手順が整備されていなかった
  • デプロイがCapistranoで行われていたが、昨今では一般的な方法ではなくなってしまったため、Docker Imageによるデプロイに移行したかった

※ 補足: 弊社では運用中のRailsアプリケーションに関する相談の中で、様々な事情から長らくアップデートされずに運用されていたRailsアプリケーションのアップグレード相談をお仕事として受けることもあります。

Dockerfile作成のポイント

aptリポジトリの指定を変更する

Ubuntu12用のパッケージは、デフォルトの archive.ubuntu.com では最早管理されていないため、URL指定を old-releases.ubuntu.com のようなリポジトリに変更する必要があります。

# Dockerfile
RUN sed -i -e 's/archive.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list

Rubyのインストールに必要なaptパッケージをインストールする

Docker Hubにある ruby:2.1-slim イメージのLayersを参考にしています。
今回インストールしたいRubyバージョンに対応する ruby:1.9.3-slim の方も確認しましたが、Layersが未記載になっており、代わりにできるだけ近いバージョンのイメージを参考にしました。
ruby:1.9.3-slim のLayers/Command確認方法を知っている方がいれば、コメント等もらえると助かります!

build-essentialsudo だけ、個人的な希望で追加しています。

# Dockerfile
RUN apt-get update && \
    apt-get install -y --no-install-recommends build-essential sudo \
    bzip2 ca-certificates libffi-dev libgdbm3 libssl-dev libyaml-dev procps zlib1g-dev \
    autoconf bison dpkg-dev gcc libbz2-dev libgdbm-dev libglib2.0-dev libncurses-dev libreadline-dev libxml2-dev libxslt-dev make ruby wget xz-utils

gemのインストールに必要なaptパッケージをインストールする

プロジェクトに応じて、利用されているgem用のパッケージをインストールすることになります。

今回手間取ったのは nokogiri のインストールです。
当初は nokogiriの同梱ライブラリを利用した環境構築 を図りましたが、解決できずに システムライブラリの利用 に切り替えました。
この場合、 nokogiri--use-system-libraries オプションを指定しておく必要があります。

# Dockerfile
RUN apt-get -y install git pkg-config libpq-dev imagemagick xvfb
# ...
RUN bundle config build.nokogiri --use-system-libraries

Rubyをインストールする

これもDocker HubのRubyイメージを参考にして、 cache.ruby-lang.org からダウンロードするようにしています。

# Dockerfile
RUN wget https://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.gz &&  \
    tar xvf ruby-$RUBY_VERSION.tar.gz &&  \
    rm ruby-$RUBY_VERSION.tar.gz && \
    cd ruby-$RUBY_VERSION && \
    ./configure --build="$gnuArch" --disable-install-doc --enable-shared && \
    make -j "$(nproc)" && \
    make install && \
    cd .. && \
    rm -rf ruby-$RUBY_VERSION

gemをインストールする

事前にBundlerのインストールが必要になります。
今回のようにRubyのバージョンが古い場合、Bundlerのバージョンも絞られることがあるので確認しておきましょう。 https://bundler.io/compatibility.html
既存のRailsプロジェクトがあるなら、 Bundlerのバージョンは Gemfile.lockBUNDLED WITH に合わせるのが無難です。

# Dockerfile
COPY Gemfile* $APP_HOME
RUN gem install bundler -v $BUNDLER_VERSION
RUN bundle config set jobs $(nproc) && bundle install

ベースイメージをRubyにしたくない特殊事情があるとき、参考にしていただけると幸いです。



CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。