Dockerの公式が出しているRubyのdocker imageではdebianやapline linuxが使用されています。mofmofではHerokuで本番環境を作っているアプリも多いのですが、HerokuではUbuntuが使われています。
そのため、ローカルで使用しているdockerでもUbuntuを使ってHerokuと環境を合わせたいねという話が開発チームの中で出ました。
開発しているアプリでHeroku-20のstackからHeroku-22にアップグレード対応するものがあったため、このタイミングでDockerのRubyをUbuntu上で動くものにしてみました。
rubylang/rubyのdocker image
こちらが今回採用したdocker imageです。Heroku-22のstackはUbuntu 22.04で動作しており、こちらのdocker imageも同様にUbuntu 22.04で動作しているため、Heroku-22のstackで動作している環境と同じ環境で動かせるということになります。
変更する上でのポイント
bundle install時のインストール先ディレクトリの権限設定
今まではこちらのようなDocker公式のdocker imageを使っていたのですが、こちらを使った場合のDockerfileでは下記のように、dockerというUSERを作って、bundle installはUSER dockerが実行する形にしていました。
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo WORKDIR /usr/src/app COPY Gemfile* ./ RUN chown docker:docker -R . USER docker RUN bundle install --jobs 4
今回も同様の形にしてdocker compose buildを実行したところ、
> [app stage-1 10/12] RUN bundle install --jobs 4: 1.917 Fetching gem metadata from https://rubygems.org/.......... 4.293 Using rake 13.0.6 4.295 Following files may not be writable, so sudo is needed: 4.295 /usr/local/bin 4.295 /usr/local/lib/ruby/gems/3.1.0 4.295 /usr/local/lib/ruby/gems/3.1.0/build_info 4.295 /usr/local/lib/ruby/gems/3.1.0/cache 4.295 /usr/local/lib/ruby/gems/3.1.0/doc 4.295 /usr/local/lib/ruby/gems/3.1.0/extensions 4.295 /usr/local/lib/ruby/gems/3.1.0/gems 4.295 /usr/local/lib/ruby/gems/3.1.0/plugins 4.295 /usr/local/lib/ruby/gems/3.1.0/specifications
ディレクトリへの書き込み権限が無いということでエラーが発生しました。最初は何が原因なのか分からなかったのですが、調査したところDocker公式のdocker imageとrubylang/rubyのdocker imageに構築時のコマンドの違いがあることが分かりました。
Docker公式のdocker imageの場合、ENV GEM_HOMEでGemのインストール先ディレクトリを設定して、そのディレクトリに対してアクセス権限を設定しているんですね。これは知りませんでした。
つまり、rubylang/rubyのdocker imageではこのようなアクセス権限の設定処理は行われていないため、USER dockerでbundle installを実行しようとすると権限エラーになったということでした。これを解消するためには、ローカルのDockerfileで同様の設定をしてやればOKです。
Docker公式のdocker imageのDockerfileを参考に、ローカルのDockerfileを下記のように書き換えてやることで、エラーを解消できました。
RUN useradd -m docker && echo "docker:docker" | chpasswd && adduser docker sudo WORKDIR /usr/src/app COPY Gemfile* ./ RUN chown docker:docker -R . ENV GEM_HOME /usr/local/bundle ENV BUNDLE_SILENCE_ROOT_WARNING=1 \ BUNDLE_APP_CONFIG="$GEM_HOME" ENV PATH $GEM_HOME/bin:$PATH RUN set -eux; \ mkdir "$GEM_HOME"; \ chmod 1777 "$GEM_HOME" USER docker RUN bundle install --jobs 4
postgresql利用時
こちらは本題とは少しズレますが、今回のアプリではDBにPostgreSQLを使用していたため、Gem pgを使っていました。bundle install時にDocker公式のdocker imageでは特にエラーは出なかったのですが、rubylang/rubyのdocker imageの場合では下記のエラーが出ました。
94.38 Unable to find PostgreSQL client library. 94.38 94.38 Please install libpq or postgresql client package like so: 94.38 sudo apt install libpq-dev 94.38 sudo yum install postgresql-devel 94.38 sudo zypper in postgresql-devel 94.38 sudo pacman -S postgresql-libs
こちらはエラーメッセージで表示されている通り、ローカルのDockerfileでライブラリをインストールしている箇所でlibpq-devを追加してやればOKです。
RUN apt-get update -qq \ && apt-get install -y --no-install-recommends \ libpq-dev \
まとめ
今回Docker公式以外のdocker imageを使ってみて、初めて構築時のコマンドに意識を向けることができました。本来の目的であるHerokuとの環境差異をなくす対応も出来、勉強になりました。