RailsのDocker環境作成

Railsチュートリアルを勉強したかったので、Docker公式を参考にDocker環境を作成したのですが、少しやり方を変えたのと、いくつかエラーに遭遇したので、そのメモを書いておきます。

前提 #

  • Docker導入済み
  • docker-composeコマンドが使用できる

Docker環境 #

作成手順 #

公式では、すべてのファイルをルートに置いていますが、自分はディレクトリ構造にしたかったので変えました。

自分の場合のディレクトリ構造

Rails
 |- ruby
   |- Dockerfile
 |- src
   |- ※以下Railsのソース
 |- docker-compose.yml
 |- entrypoint.sh
 |- README.md

1.Dockerfileを作成

FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /src
WORKDIR /src
COPY src/Gemfile /src/Gemfile
COPY src/Gemfile.lock /src/Gemfile.lock
RUN bundle install
COPY ./src /src

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

2.src/Gemfileを作成

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

3.src/Gemfile.lockを作成(中身は空でOK)

4.entrypoint.shを作成

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

5.docker-compose.ymlを作成

version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/
  web:
    build:
      context: ./
      dockerfile: ./ruby/Dockerfile
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - ./src:/src
    ports:
      - "3000:3000"
    depends_on:
      - db

6.ビルドして、Railsプロジェクトを作成

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

7.もう一度、コンテナをビルド(rails newでGemfileの内容が変わったため)

$ docker-compose build

8.データベースの接続設定を記述(src/config/database.yml)
データベース名は任意の名前でOK

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password:
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test

Dockerの起動 #

1.コンテナの起動

$ docker-compose up -d

2.初期DBの作成

$ docker-compose run web rake db:create

以下のように表示されれば無事データベースが作成されています。

Starting rails_db_1 ... done
Created database 'myapp_develop'
Created database 'myapp_test'

3.ブラウザでアクセス
以下のような画面が表示されればOKです。
localhost:3000(DockerホストIP):3000
Railsトップ画面

遭遇したエラー #

ビルドコンテキスト外のファイルをCOPYしようとしてエラー #

参考:docker-composeでADDやCOPYをする際に注意すること

docker-compose.ymlの以下の部分を

 web:
    build:
      context: ./
      dockerfile: ./ruby/Dockerfile

最初はこうしていました。

 web:
    build: ./ruby

すると、Dockerfileの中で、GemfileをCOPYするところでエラーになりました。

原因としては、ビルドコンテキスト外のファイルでCOPYやADDができないとのことでした。つまりビルドコンテキストに./rubyを指定しているので、この配下にあるファイルしか指定できないようです。
なので、buildの個所をcontextdockerfileにわけて記述することで対応しました。

なお、補足として、DockerfileのCOPYなどで指定するホスト側のパスは、ビルドコンテキストを基準としたパスになります。

COPY src/Gemfile /src/Gemfile ←ビルドコンテキスト(./)からのパス


コンテナ起動時にexited with code 1になる #

参考: docker-compose upするとコンテナが一瞬でexited with code 1する話

docker-compose upで起動するとコンテナがうまく起動しませんでした。
原因としては、コンテナ起動時に実行しているentrypoint.shの改行コードがCRLF(Windows標準)になっていたことでした。
ここは改行コードをLF(Linux標準)に変更して対応しました。

postgresコンテナの起動に失敗する #

参考:Docker for WindowsとLaradocでpostgresのコンテナが起動できない場合の対処

コンテナ起動に失敗し、ログを見るとFATAL: data directory "/var/lib/postgresql/data" has wrong ownershipと表示されて
いました。
どうもvolumeマウントに失敗していたようです。

docker-compose.ymlでマウントのパスを/var/lib/postgresql/dataから/var/lib/postgresql/に修正すると、なぜか起動するようになりました。

  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/ ←パス末尾のdataをなくす

Docker公式で案内があったのはありがたかったのですが、ディレクトリ構造を変更したこともあり、いくつかエラーに遭遇しました。
とりあえず無事起動できてよかったです。

Railsチュートリアルは一応一通り終わったので、AWSの勉強に戻ろうかと思います。資格取らねば…。

参考リンクまとめ #