#はじめてのDockerでRails開発環境構築 [NGINX + Rails 5 (puma) + PostgreSQL]
それなりに時間を書けて取り組んだので改善点等コメントいただけると嬉しいです
GitHubにコードも上げてありますので、必要があれば公開いたします同様にコメントください
Rails6版できました
- コマンドひとつ、5分でRails環境構築
- Rails6で躓きがちな、webpackによるCSS, JavaScript管理について対策済み
- Bootstrap自動インストール
- より新しいComposeの使用を反映
なぜやるか
- 今後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を用意
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
コマンドで上書きされる)
source 'https://rubygems.org'
gem 'rails', '~>5'
Gemfile.lock
空のファイルで良いのでtouch
コマンドのみ
touch Gemfile.lock
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ファイルを用意
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
ファイル
(ログの部分はコメントアウトを外すと、ディレクトリが見つからないとエラーが出ます。どうしても解決できずコメントアウトのまま)
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:
は書いているものの、うまく使えていないと思います)
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
の中身を以下で置き換える
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
の中身を以下で置き換える
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
完成
最後に
これ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