Rails 6 の環境をdockerで構築する

内容に誤りがあったため、最初に公開したときから大幅に修正を加えました

なぜ書くか

docker公式のrailsのQuickstart のページに、Rails でYay railsする手順は書いてあります。 しかし実はこちらの手順ではDockerfile内でのユーザーがrootのままであるため、そのまま開発を進めようとすると問題が発生します。

hostは一般ユーザーですが、container内はroot のため、コンテナ内で作成したファイルをhost側で何の気なしに編集しようとすると、編集できないという問題です。 この問題はおそらくmacでは起こらないのですが、linuxでdockerをいじるときはあるあるです。 また、rails のように、フレームワークのエンジンがファイルを生成するような場合にcriticalな問題でもあります。host側でエディタを使いたい場合などは、フレームワークが生成したファイルの権限をいちいちsudo で書き換えて、、などする必要があります。面倒でやってられません

なお、host側で作成したファイルはcontainer側で問題なく動かせるので、実行環境としてdockerを使う分には、困ることは少ないでしょう。

今回はrailsなので、権限問題には何かしらの対処が必要です。ここでは素直にイメージ作成時にユーザーを作成する方針を取りました。 別の解決策として、rootless docker (dockerをユーザーモードで使う) も考えられます。ただ、それはそれで過去に何度かややこしい問題に遭遇してるので、今回はやめました。

Dockerfileを書く際にもいろいろ苦労したので、その結果を残します

また、上記docker公式のrailsのQuickstart は少々古く、rails のバージョンが5です。 railsのバージョンを6にして同様の手順をふもうとすると、さらに別の問題が発生します。 それは、Yarn not installed. というエラーで先に進めないことです。

Qiitaで見つかった記事によるとRails6でwebpackerが標準になったことにより、Railsアプリの開発環境にyarnのインストールが必要になったということです。

この yarnのインストール方法も、nodeを経由したりと選択肢が複数あり、いろいろ試行錯誤しました

おおまかにはquickstartと同じです。

Dockerfile

以下のようにDockerfileを作成します。

FROM ruby:2.7.4

ENV LANG C.UTF-8
ENV WORKSPACE=/usr/local/src

RUN echo 'deb http://ftp.jp.debian.org/debian sid main ' >> /etc/apt/sources.list && \
  curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
  echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

# install bundler.
RUN apt-get update && \
    apt-get install -y vim less && \
    apt-get install -y build-essential libpq-dev yarn postgresql-client && \
    apt-get clean && \
    rm -r /var/lib/apt/lists/*

# create user and group.
RUN groupadd -r --gid 1000 rails && \
    useradd -m -r --uid 1000 --gid 1000 rails

# create directory.
RUN mkdir -p $WORKSPACE && \
    chown -R rails:rails $WORKSPACE

USER rails
WORKDIR $WORKSPACE

RUN gem install bundler

# bundle install
COPY --chown=rails:rails Gemfile $WORKSPACE/Gemfile
RUN bundle install
EXPOSE  3000
CMD ["rails", "server", "-b", "0.0.0.0"]

これがrailsのイメージになります ポイントは

  • ruby 2.7 を使ってること
  • yarnをインストールする部分
  • Gemfileのコピー時に --chown オプションを指定していること

です。

Gemfile

Dockerfile内にでてきたGemfileはhost側に作成して、以下のようにしておきます

source 'https://rubygems.org'
gem 'rails', '~>6'

docker-compose

DBも含めた全体像を理解したいと思うので、 docker-compose.yml を以下のように作成します

version: "3.9"
services:
  db:
    image: postgres
    volumes:
      - database:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle install && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  database:

特にポイントはないです。

ビルドとDB設定

quickstartの手順と同様、

docker-compose run --no-deps web rails new . --force --database=postgresql

作成されたconfig/database.yml に host, username, passwordを設定します。 こちらもquickstartと同様です。

  host: db
  username: postgres
  password: password

docker-compose exec web bundle ex rails db:create すると Yay! がみれます 開発も問題なく行えます

いじょう。

おわりに

開発ができるようになるまで結構苦労したのですが、結論は簡単なものですね。 database.yml の修正などは手動ではなく、ファイルのコピーなどでやるようにするのがよさそうです。

終わりなので苦労した部分もメモを残します

yarnのインストール

詳細は省きますが、nodeのインストール方法は複数あり、私にとってははまりポイントでした。

yarnはnpm 経由でインストールする方法が推奨されているようでした。

私が参考にしたサイトでは、npmはnodeをインストールすると依存パッケージとして同時にインストールされると書いてありましたが、nodeのインストール方法も複数あり、誤った方法でnodeをインストールするとnpm がついてきません。

最終的には、前述の通り、yarnを直接apt-getすることにしました

--chown でコピー時に権限を設定

bundle installする際に、Gemfileの権限がbundle installを実行するユーザーの書き込み可能な権限になっている必要があります。 bundle installは一般ユーザーで実行したいので、Gemfileの権限も合わせます

ちなみに、コピーしてから権限を付与しても一緒のはずです。

追記

bash/make 等は書いてないですがbaseのコードはこちらに作りました

github.com