Help us understand the problem. What is going on with this article?

Docker ComposeでRails+PostgreSQLの環境構築

docker-composeの勉強に,Railsの環境構築をやってみたのでハマったところも含めてメモ.
参考: Quickstart: Compose and Rails

実行環境

  • MacBook Pro (13-inch, 2019)
    • macOS Catalina version 10.15
  • Docker version 19.03.5
  • docker-compose version 1.24.1
  • ruby 2.5.7
  • Rails 5.2.4.1
  • postgres (PostgreSQL) 12.2

構築手順

Dockerfileの作成

参考ページそのままに,Dockerfileを作成.

Dockerfile
FROM ruby:2.5

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client

RUN mkdir /myapp
WORKDIR /myapp

COPY Gemfile /myapp/Gemfile                                 
COPY Gemfile.lock /myapp/Gemfile.lock

RUN bundle install

COPY . /myapp

COPY entrypoint.sh /usr/bin
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

Gemfileの作成

同じくGemfileを作成.

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

Gemfile.lockの作成

空のGemfile.lockを作成.

$ touch Gemfile.lock

entrypoint scriptの作成

server.pidが存在するとサーバの再起動が失敗するというRails特有の問題があり,それを修正するためのentrypoint scriptを作成.

entrypoint.sh
#!/bin/bash
set -e

rm -f /myapp/tmp/pids/server.pid

exec "$@"

docker-compose.ymlの作成

DBサーバとAPPサーバを立てるためのdocker-compose.ymlを作成.拡張子はymlyamlのどちらでも大丈夫.
なお,参考ページに沿った手順で進めていますが,以下のdocker-compose.yamlはDBのパスワードの設定が不足しているため注意(後述).

docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

Railsアプリの作成

以下のコマンドを実行し,Railsアプリのスケルトンを作成.

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

DBの指定

Railsはデフォルトでlocalhost上で起動しているデータベースを探すので,dbコンテナを使うようconfig/database.ymlを以下の内容に置き換えます.
なお,先程のdocker-compose.ymlと同じく,DBのパスワードの設定が不足しています(後述).

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password:
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test

コンテナの起動(失敗,修正)

準備ができたので,以下のコマンドでコンテナを立ち上げます.

$ docker-compose up

すると,以下のエラーが表示されてdbコンテナが落ちます(本来ならDBの接続待ちのメッセージが表示される).

db_1 | Error: Database is uninitialized and superuser password is not specified.
db_1 | You must specify POSTGRES_PASSWORD to a non-empty value for the
db_1 | superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
db_1 |
db_1 | You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all
db_1 | connections without a password. This is not recommended.

postgresでパスワード無しでのログインが拒否されているため,config/database.ymlにパスワードを追記.
さらにdocker-compose.ymlにもパスワードを追記.

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: postgres # ここを追記
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test
docker-compose.yml
version: '3'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment: # ここから以下2行を追記
      POSTGRES_PASSWORD: postgres
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

一旦落ちたdbコンテナも含めて削除し,再度docker-compose upを実行.

$ docker-compose stop
$ docker rm $(docker ps -aq)
$ docker-compose up

すると,今度はdbコンテナのログでdatabase system is ready to accept connections
というメッセージが確認できます.

データベースの作成

最後に,以下のコマンドでデータベースを作成します.

$ docker-compose run web rake db:create
Starting ror_db_1 ... done
Created database 'myapp_development'
Created database 'myapp_test'

完成

これで全ての設定が完了したので,localhost:3000にアクセスするとRailsの初期ページが表示されます.

スクリーンショット 2020-03-10 22.14.46.png

youril
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away