LoginSignup
24

More than 3 years have passed since last update.

はじめてのDockerでRails開発環境構築 [NGINX + Rails 5 (puma) + PostgreSQL]

Last updated at Posted at 2020-06-27

はじめてのDockerでRails開発環境構築 [NGINX + Rails 5 (puma) + PostgreSQL]

それなりに時間を書けて取り組んだので改善点等コメントいただけると嬉しいです
GitHubにコードも上げてありますので、必要があれば公開いたします同様にコメントください

Rails6版できました

  • コマンドひとつ、5分でRails環境構築
  • Rails6で躓きがちな、webpackによるCSS, JavaScript管理について対策済み
  • Bootstrap自動インストール
  • より新しいComposeの使用を反映

コマンドひとつ、5分でRails6の開発環境構築 on Docker - Rails6 + Nginx + PostgreSQL + Webpack (Bootstrap install済) - Qiita

なぜやるか

  • 今後AWSのEC2上にNGINX + puma (Rails) + PostgreSQLの環境でアプリをデプロイしたい
  • 開発環境も同じ構成でやりたい
  • 実務での開発を意識してDockerを使ってローカル開発環境を構築したい
  • Railsチュートリアルでお世話になったAWS Cloud9ではなく、VS Codeを使いたい

何を得たか

  • Dockerの基礎知識、概念
  • 快適なローカル開発環境 (VSCode素敵)
  • 初学者が開発環境構築までやると時間対効果よくない(丸一日かかりました...)
  • ただし、一度構築してしまえば環境の再現は恐ろしく簡単、環境の共有という視点も納得(シェル書けばあっという間?)
  • AWSデプロイもこのまま行けそう、という謎の自信
  • 一次情報大事という気づき
  • Railsチュートリアルの製作者たちが様々な工夫で環境構築のハードルを劇的に下げてくれていることへの感謝と、それ以上の柔軟性と実用性を提供してくれるDockerの素晴らしさ

結論

手順通りに進むと、表題のRails開発環境が手に入る、はずです

初学者がポートフォリオ作成のロードマップの中でDockerを導入するのであれば、
先人のお知恵を借りて、既存の開発環境を自分のローカル環境に取り入れるくらいの感覚のほうが良いかもしれない

時間をかけてRailsチュートリアルに取り組める、かつ私のような物好きは
Dockerで環境構築から初めて、環境の差による不具合を敢えて乗り越えて行くのも粋かもしれない

環境・スキル

  • Mac OS (Mojave)
  • Docker for Mac, Docker composeインストール済み
  • Ruby 2.5
  • Rails 5.2.4.3
  • Nginx 1.15.8
  • PostgreSQL
  • Rails チュートリアル1周目、Docker初心者

参考

Docker公式docs: 基本的にこの流れを踏襲しています
Quickstart: Compose and Rails | Docker Documentation

nginx公式docs: 設定例
Full Example Configuration | NGINX

nginxほか設定例
nginxについてまとめ(設定編) - Qiita

pumaの設定はこちらを参考
既存のRailsアプリのローカル開発環境をDockerの仮想環境に切り替える - りょ〜Blog

ボリュームマウントの構成はこちら
Docker + Rails + Puma + Nginx + MySQL - Qiita

備忘録

ディレクトリ構成

(予め用意するもののみ記載)

sample_app ---- Dockerfile
            |-- Gemfile
            |-- Gemfile.lock
            |-- nginx ---- Dokerfile
            |          |-- nginx.conf
            |
            |-- config ---- database.yml (後で自動生成)
            |           |-- puma.rb (後で自動生成)
            |
            |-- environments --db.env (今回うまく使えてません)
            |
            |-- docker-compose.yml
            |-- entrypoint.sh


Dockerfile (Ruby)作成

まずはruby用の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

# 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

# puma.sockを配置するディレクトリを作成
RUN mkdir -p tmp/sockets

Gemfile(これはあとのrails newコマンドで上書きされる)

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

Gemfile.lock
空のファイルで良いのでtouchコマンドのみ

Gemfile.lock
touch Gemfile.lock

entrypoint.sh

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 "$@"

Dockerfile (NGINX)作成

次にnginx用のDockerファイルを用意

/nginx/Dockerfile
FROM nginx:1.15.8

# インクルード用のディレクトリ内を削除
RUN rm -f /etc/nginx/conf.d/*

# Nginxの設定ファイルをコンテナにコピー
ADD nginx.conf /etc/nginx/myapp.conf

# ビルド完了後にNginxを起動
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/myapp.conf

上で呼び出される
nginx.confファイル
(ログの部分はコメントアウトを外すと、ディレクトリが見つからないとエラーが出ます。どうしても解決できずコメントアウトのまま)

/nginx/nginx.conf
user  root;
worker_processes  1;

events{
    worker_connections  512;
}

# ソケット接続
http {
  upstream myapp{
    server unix:///myapp/tmp/sockets/puma.sock;
  }
  server { # simple load balancing
    listen 80;
    server_name localhost;

    #ログを記録しようとするとエラーが生じます
    #root /myapp/public;
    #access_log logs/access.log;
    #error_log logs/error.log;

    location / {
      proxy_pass http://myapp;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
    }
  }
}

Docker-composeを作成

これらのコンテナをうまくゴニョゴニョしてくれるというdocker-compose
docker-compose.ymlを以下のように記述
env_file:は書いているものの、うまく使えていないと思います)

docker-compose.yml
version: '3'
services:
  app:
    build: .
    env_file:
      - ./environments/db.env
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec puma -C config/puma.rb"
    volumes:
      - .:/myapp
      - public-data:/myapp/public
      - tmp-data:/myapp/tmp
      - log-data:/myapp/log
    depends_on:
      - db
  db:
    image: postgres
    env_file:
      - ./environments/db.env
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: nginx
    volumes:
      - public-data:/myapp/public
      - tmp-data:/myapp/tmp
    ports:
      - "80:80"
    depends_on:
      - app
volumes:
    public-data:
    tmp-data:
    log-data:
    db-data:

Gemインストール

カレントディレクトリをDocker fileが配置されている場所に移動し
以下のdocker-compose runコマンドでRailsを展開する
(この時Gemファイルが上書きされるはず)

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

Gemをインストールするためにdocker-compose buildコマンドを実施
(Gemファイルおよび、Dockerファイルに変更がある場合のみ再度このコマンドが必要)

Now that you’ve got a new Gemfile, you need to build the image again. (This, and changes to the Gemfile or the Dockerfile, should be the only times you’ll need to rebuild.)
(Docker 公式 docs)

docker-compose build

設定ファイルの修正

config/puma.rbの中身を以下で置き換える

/sample_app/config/puma.rb
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
threads threads_count, threads_count
port        ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart

app_root = File.expand_path("../..", __FILE__)
bind "unix://#{app_root}/tmp/sockets/puma.sock"

stdout_redirect "#{app_root}/log/puma.stdout.log", "#{app_root}/log/puma.stderr.log", true

config/database.ymlの中身を以下で置き換える

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

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

コンテナを起動

docker-compose upコマンドでアプリたちをを起動する

docker-compose up

処理が止まっているように見えてもエラーが出ていなければサーバーが起動しているはずです、
docker-compose up -dでターミナルの入力を継続できます

doker psで起動しているコンテナを確認すると
nginx(sample_app_web), puma(sample_app_app), DB(postgres)の3つが起動しているはず

$ docker ps
CONTAINER ID        IMAGE             COMMAND                                ...   PORTS                NAMES
7188a5bb9d3c        sample_app_web    "/bin/sh -c '/usr/sb…"   ...   0.0.0.0:80->80/tcp   sample_app_web_1
41759b7d078e        sample_app_app    "entrypoint.sh bash …"   ...                        sample_app_app_1
1c81a75b5c22        postgres          "docker-entrypoint.s…"   ...   5432/tcp             sample_app_db_1

この時点でlocalhost:80にアクセスすると、
Railsのエラー画面、あともう少し
データベースがないよと言われるので

DBを作成する

docker-compose run app rake db:create

完成

再びlocalhost:80で...
スクリーンショット 2020-06-27 22.14.46.png

最後に

これRailsのコマンドはどうやって打つの?という残念なレベル...
docker-compose run appに続けて記述するそうです
appはRailsが動いているコンテナですね

$ docker-compose run app rails -v
Starting sample_app_db_1 ... done
Rails 5.2.4.3

動いているコンテナを終了するのは
(これをやらないと次回起動時エラーが出る)

$ docker-compose down

再度起動するには

$ docker-compose up

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
24