LoginSignup
2
1

More than 1 year has passed since last update.

Rails+PostgreSQLアプリをDocker化する手順

Posted at

RailsアプリをDocker化する手順

既存のRailsアプリをDocker上で動かせるように環境構築を行います。

  1. Railsアプリを用意する
  2. Dockerfileを作成する
  3. docker-compose.ymlを作成する
  4. Gemfileを編集する
  5. config/database.ymlを編集する
  6. Dockerイメージをビルドする
  7. Dockerコンテナを作成し起動する
  8. webコンテナに対してデータベースを作成するコマンドを実行する
  9. http://localhost:3000 にアクセスして表示を確認する

Railsアプリを用意する

使用するバージョンは以下の通り。

  • ruby 3.0.2
  • rails 6.0.3
  • gem 3.2.22
  • bundler 2.2.22
  • node 12.22.12
  • npm 6.14.16
  • yarn 1.22.19
  • PostgreSQL 13.9

Dockerの基本的な使い方

Dockerは基本的に以下の流れで環境構築を行う。

  1. Docker Hubからイメージを取得する、またはDockerfileでイメージをビルドする
  2. イメージからコンテナを作成し起動する
  3. コンテナで任意の操作を行う

Dockerfileを作成する

Dockerfileを使ってコンテナの元となるイメージを作成する。

Dockerfileの内容は以下の通り。

# ベースイメージを指定する
FROM node:12 as node
FROM ruby:3.0.2

# ワーキングディレクトリを指定する
WORKDIR /src

# マルチステージビルドでrubyコンテナにnodeとnpmを追加する
COPY --from=node /usr/local/bin/node /usr/local/bin/
COPY --from=node /usr/local/lib/node_modules/ /usr/local/lib/node_modules/

RUN ln -fs /usr/local/bin/node /usr/local/bin/nodejs \
    && ln -fs /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
    && ln -fs /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npx

# aptを更新し、必要なパッケージをインストールする
RUN apt-get update && apt-get install -y \
    build-essential \
    libpq-dev \
    postgresql-client

# ホストのGemfileとGemfile.lockをコンテナの/src/にコピーする
COPY Gemfile Gemfile.lock /src/

# Gemをインストールする
RUN bundle install

# ホストのpackage.jsonとyarn.lockをコンテナ内にコピーする
COPY package.json yarn.lock /src/

# npmを使ってyarnをグローバルインストールする
RUN npm install --global yarn

# yarnを更新する
RUN yarn install

ベースイメージを指定する

FROM node:12 as node
FROM ruby:3.0.2

Fromは使用するイメージを指定する。

Rubyとnodeのイメージを使う。イメージ名の後ろはバージョンを指定する。asを使ってイメージ名を変更できる。

基本的にDockerfileは1つのファイルにつき1つのイメージだが、ここではマルチステージビルドを使ってnodeをインストールする。

マルチステージビルドによって複数のイメージを同時にビルドでき、イメージの容量を小さくできる。

ワークディレクトリを指定する

WORKDIR /src

WORKDIRはDockerfileの内容を実行するディレクトリを指定する命令。

マルチステージビルドでrubyコンテナにnodeとnpmを追加する

マルチステージビルドを行うために、nodeとnpmのバイナリファイルをコピーして、シンボリックリンクを貼る。

COPY --from=node /usr/local/bin/node /usr/local/bin/
COPY --from=node /usr/local/lib/node_modules/ /usr/local/lib/node_modules/

COPYはホストのファイルをコンテナ内にコピーする命令。

コマンドの最後にある\はコマンドを改行するための文字で、2行目と3行目にある&&はコマンドをつなげて同時に実行するための文字。

RUN ln -fs /usr/local/bin/node /usr/local/bin/nodejs \
    && ln -fs /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
    && ln -fs /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npx

RUNは後ろに記述したコマンドをコンテナ内で実行する命令。

lnはファイルのリンクを作成するLinuxのコマンドで、-fsオプションでシンボリックリンクを作成する。

aptを更新し、必要なパッケージをインストールする

RUN apt-get update && apt-get install -y \
    build-essential \
    libpq-dev \
    postgresql-client

aptはDebian系のLinuxディストリビューションのパッケージ管理システムのことで、apt-getでコマンドを実行できる。

apt-get updateでaptを更新する。

apt-get install -yでパッケージをインストールする。-yのオプションをつけることで、インストール時に聞かれる質問を飛ばすことができる。

build-essentialは開発に必須のビルドツールを提供しているLinuxのパッケージ。

libpq-devはPostgreSQLクライアントのヘッダやライブラリを含むパッケージで、PostgreSQLを使うために必要になる。

postgresql-clientはPostgreSQLのクライアントアプリケーションであるpsqlを使えるようにするためのパッケージ。

ホストのGemfileとGemfile.lockをコンテナの/src/にコピーする

COPY Gemfile Gemfile.lock /src/

COPYはホストのファイルをコンテナにコピーする命令。ホストとは自分のPCのこと。ここではGemfileとGemfile.lockをコピーする。

GemfileはRubyのパッケージ管理システムであるGemを使うためのファイル。RailsもGemを使ってインストールする。

Gemfile.lockはインストールされているパッケージとそのバージョンが記述されているファイル。

既存のRailsアプリなので、GemfileとGemfile.lockはすでに用意されている。

Gemをインストールする

RUN bundle install

bundle installによって、コンテナ側でコピーしたホストのGemfileの内容を元にパッケージをインストールする。

bundleはgemを管理するライブラリのこと。bundleを使うことで、gemの依存関係や互換性を管理してくれ、gemのパッケージを一括でインストールしたりできる。

ホストのpackage.jsonとyarn.lockをコンテナ内にコピーする

COPY package.json yarn.lock /src/

package.jsonはnpmのパッケージ名が記述されたファイル。npmとはNode.jsのパッケージ管理システムのこと。

yarn.lockはyarnのlockファイル。yarnとはnpm同様、Node.jsのパッケージ管理システムで、npmより動作が速い。
yarnではなくnpmを使ってもいい。npmの場合はpackage.lock.jsonを使う。

npmを使ってyarnをグローバルインストールする

RUN npm install --global yarn

npmを使ってyarnをグローバルインストールする。

yarnを更新する

RUN yarn install

yarn installによってコピーしたpackage.jsonの内容でインストールされる。

docker-compose.ymlを作成する

Docker Composeを使用するためにdocker-compose.ymlを作成する。今回はDockerfileと同じディレクトリに作成する。

Docker Composeを使えば、複数のコンテナを同時に操作でき、またコンテナ同士で通信を行うためのネットワークを自動で作成できる。

docker-comopose.ymlの内容は以下の通り。

# Docker Composeのバージョンを指定する
version: '3'

# 各コンテナを指定する
services:

  # webコンテナ
  web:
    # コマンドを実行するディレクトリにあるDockerfileを使ってビルドする
    build: .

    # ホストの3000番ポートとコンテナの3000番ポートを紐づける
    ports:
      - '3000:3000'

    # コンテナを起動した時にrails serverを起動する
    command: bundle exec rails s -p 3000 -b '0.0.0.0' 

    # docker-compose.ymlと同じディレクトリにあるファイルやフォルダをコンテナの/src配下にマウントする(ホストでの変更がコンテナに反映されるようにする)
    volumes:
      - .:/src

    # dbコンテナを起動してからwebを起動する
    depends_on:
      - db
    
  # dbコンテナ
  db:
    # Docker Hubのイメージを使う
    image: postgres

    # コンテナに環境変数を設定する
    environment:
      - POSTGRES_PASSWORD=password

Gemfileを編集する

railsでPostgreSQLを使うために、Gemfileに以下のコードを追記する。

gem 'pg', '~> 0.18.4'

config/database.ymlを編集する

Railsアプリを作成するとデータベースの設定を行うconfig/database.ymlが作られており、デフォルトではsqliteになっているのでこれをpostgresqlに変更する。

database.ymlの内容は以下の通り。

default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: rails-docker_development

test:
  <<: *default
  database: rails-docker_test

production:
  <<: *default
  database: rails-docker_production

イメージをビルドする

Docker Composeを使ってイメージをビルドする。

docker compose build

コンテナを作成し起動する

ビルドしたイメージを使ってコンテナを作成し起動する。

docker compose up -d

webコンテナでデータベースを作成する

起動したwebコンテナでrailsアプリのデータベースを作成する。

docker compose exec web rails db:create db:migrate

docker compose execコマンドは起動しているコンテナに対して後の命令を実行する。ここではwebコンテナに対してコマンドを実行する。

execの後ろはコンテナの名前を指定する。コンテナの名前はdocker-compose.ymlを使っていればservicesに記述した名前を使う。

web以降のコマンドはrailsのコマンドを実行している。db:createでデータベースを作成し、db:migrateでデータベースのテーブルを作成する。

Railsのページを確認する

ここまでの操作がうまく実行できていれば、http://localhost:3000 にアクセスするとRailsのページが表示される。

3000というのはdocker-compose.yml内で記述したポート番号。もし違うアプリで3000番を使っている場合は他の番号を指定する。

※webコンテナがExitedになってしまう場合

webコンテナが起動してもすぐExitedになってしまうエラーが発生。

エラーメッセージ

/usr/local/bundle/gems/webpacker-5.4.4/lib/webpacker/configuration.rb:103:in `rescue in load': Webpacker configuration file not found /src/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /src/config/webpacker.yml (RuntimeError)

とりあえずconfig/webpacker.ymlを作成し、以下の内容を記述。

# Note: You must restart bin/webpack-dev-server for changes to take effect

default: &default
  source_path: app/javascript
  source_entry_path: packs
  public_root_path: public
  public_output_path: packs
  cache_path: tmp/cache/webpacker
  webpack_compile_output: true

  # Additional paths webpack should lookup modules
  # ['app/assets', 'engine/foo/app/assets']
  additional_paths: []

  # Reload manifest.json on all requests so we reload latest compiled packs
  cache_manifest: false

  # Extract and emit a css file
  extract_css: false

  static_assets_extensions:
    - .jpg
    - .jpeg
    - .png
    - .gif
    - .tiff
    - .ico
    - .svg
    - .eot
    - .otf
    - .ttf
    - .woff
    - .woff2

  extensions:
    - .mjs
    - .js
    - .sass
    - .scss
    - .css
    - .module.sass
    - .module.scss
    - .module.css
    - .png
    - .svg
    - .gif
    - .jpeg
    - .jpg

development:
  <<: *default
  compile: true

  # Reference: https://webpack.js.org/configuration/dev-server/
  dev_server:
    https: false
    host: localhost
    port: 3035
    public: localhost:3035
    hmr: false
    # Inline should be set to true if using HMR
    inline: true
    overlay: true
    compress: true
    disable_host_check: true
    use_local_ip: false
    quiet: false
    pretty: false
    headers:
      'Access-Control-Allow-Origin': '*'
    watch_options:
      ignored: '**/node_modules/**'


test:
  <<: *default
  compile: true

  # Compile test packs to a separate directory
  public_output_path: packs-test

production:
  <<: *default

  # Production depends on precompilation of packs prior to booting for performance.
  compile: false

  # Extract and emit a css file
  extract_css: true

  # Cache manifest.json for performance
  cache_manifest: true

うまく起動した。

webpackerはrailsのフロントの部分を便利に書けるもので、rails6では標準になっているらしい。

参考

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1