#概要
Dockerを使用してRuby on Railsの開発環境を構築してみました。
Dockerを使用すると、ローカル環境に左右されず開発環境を構築でき、開発環境から本番環境への移行も設定を変更せず移行できるため、多くの開発現場で使用されている。
独学でDockerを勉強した私が作成した最終的な設定になります。
#バージョン
Ruby 2.6.3
Ruby on Rails 5.2.0
Docker 19.03.13
docker compose 1.27.4
MySQL 5.7
Nginx 1.15.8
#前提
- docker、docker-composeはインストール済みである。
#ディレクトリ構成
./myapp
├── containers
│ └── nginx
│ ├── Dockerfile
│ └── nginx.conf
├── .env
├── docker-compose.yml
├── Dockerfile
├── Gemfile
└── Gemfile.lock
#各ディレクトリ、ファイルの詳細
Rails用Dockerfile
FROM ruby:2.6.3
RUN apt-get update\
&& apt-get install -y --no-install-recommends\
libpq-dev\
nodejs\
vim\
mariadb-client\
build-essential\
&& apt-get clean\
&& rm -rf /var/lib/apt/list/*
RUN mkdir /myproject
WORKDIR /myproject
COPY Gemfile /myproject/Gemfile
COPY Gemfile.lock /myproject/Gemfile.lock
RUN gem install bundler
RUN bundle install
COPY . /myproject
RUN mkdir -p tmp/sockets
RUN mkdir -p tmp/pids
Gemfile
source 'https://rubygems.org'
gem 'rails', '5.2.0'
Gemfile.lock
中身は空でOK
Nginx用Dockerfile
FROM nginx:1.15.8
RUN rm -f /etc/nginx/conf.d/*
ADD nginx.conf /etc/nginx/conf.d/myproject.conf
CMD /usr/sbin/nginx -g 'daemon off;' -c /etc/nginx/nginx.conf
Nginx.confファイル
upstream myproject {
server unix:///myproject/tmp/sockets/puma.sock;
}
server {
listen 80;
server_name IPアドレス [or localhost];
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
root /myproject/public;
client_max_body_size 100m;
error_page 404 /404.html;
error_page 505 502 503 504 /500.html;
try_files $uri/index.html $uri @myproject;
keepalive_timeout 5;
location @myproject {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://myproject;
}
}
.envファイル
MYSQL_ROOT_PASSWORD=password
MYSQL_USER=username
MYSQL_PASSWORD=password
MYSQL_DATABASE=docker_database
docker-compose.ymlファイル
version: '3'
services:
db:
image: mysql:5.7
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
env_file:
- ./.env
volumes:
- mysql-data:/var/lib/mysql
ports:
- "4306:3306"
app:
build: .
env_file:
- ./.env
command: bundle exec puma -C config/puma.rb
init: true
volumes:
- .:/myproject
- public-data:/myproject/public
- tmp-data:/myproject/tmp
- log-data:/myproject/log
depends_on:
- db
web:
build:
context: containers/nginx
init: true
volumes:
- public-data:/myproject/public
- tmp-data:/myproject/tmp
ports:
- 80:80
depends_on:
- app
volumes:
mysql-data:
public-data:
tmp-data:
log-data:
#Railsアプリケーションの設定
まずrails newにてRailsアプリケーションを作成します。
$ docker-compose run --rm app bundle exec rails new . --force --database=mysql --skip-bundle
続いて、configディレクトリ内のpumaファイルを編集します。
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
database.ymlを編集します。
default: &default
adapter: mysql2
charset: utf8
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: <%= ENV.fetch("MYSQL_USER") { 'root' } %>
password: <%= ENV.fetch("MYSQL_PASSWORD") { 'password' } %>
host: db
development:
<<: *default
database: docker_database
test:
<<: *default
database: myproject_test
production:
<<: *default
database: myproject_production
username: myproject
password: <%= ENV['MYPROJECT_DATABASE_PASSWORD'] %>
#コンテナの起動
ここまで準備ができましたら、コンテナを起動します。
$ docker-compose build
ビルドが完了したら
$ docker-compose up
ここでlocalhostにアクセスしてRailsのページが立ち上がれば完成です。
#既存のRailsアプリをdockerで環境構築する場合
アプリケーションのフォルダの中に以下のディレクトリ、ファイル類を追加します。
(ファイルの設定は一から作る場合と一緒です。)
./myapp
├── containers
│ └── nginx
│ ├── Dockerfile
│ └── nginx.conf
│
│ その他のファイル
│
├── .env
├── docker-compose.yml
└── Dockerfile
その後、ビルドを行います。アプリケーションはすでにあるので、rails newコマンドをする必要はありません。
データベースは一度migrateする必要があるので、ビルド後にmigrateを行います。
$ docker-compose build
ビルドが完了したら
$ docker-compose up -d
$ docker-compose exec app rails db:migrate
以上でlocalhostにアクセスすれば既存のアプリケーションにdockerを導入することができると思います。
#補足
私もまだまだ勉強不足でして、途中でエラーになったりとかなり苦戦しました。
その都度、ネットで調べたりして解決できました。
#ハマったエラー
- rails newでrailsファイルが作成できない。
参考ページでは
$ docker-compose run --rm app rails new . --force --database=mysql --skip-bundle
となっていましたが、
$ docker-compose run --rm app bundle exec rails new . --force --database=mysql --skip-bundle
でRailsファイル群をインストールすることができました。
- docker-compose buildが通らない。
$ docker-compose build
...
Bundler could not find compatible versions for gem "sprockets":
In snapshot (Gemfile.lock):
sprockets (= 4.0.2)
In Gemfile:
sass-rails (~> 5.1) x86_64-linux was resolved to 5.1.0, which depends on
sprockets (>= 2.8, < 4.0)
rails (~> 5.2.0) x86_64-linux was resolved to 5.2.0, which depends on
sprockets-rails (>= 2.0.0) x86_64-linux was resolved to 3.2.2, which
depends on
sprockets (>= 3.0.0)
Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
ERROR: Service 'app' failed to build : The command '/bin/sh -c bundle install' returned a non-zero code: 6
bundle updateをするよう言われているので、bundle updateを行います。
$ docker-compose run app bundle update
その後
$ docker-compose build
#まとめ
dockerでの環境構築はなんとかできましたが、まだまだ勉強不足で苦戦しました。
私が初めてdockerを使い始めたときは、既存のアプリケーションをdocker化しました。その後、新規環境構築からdockerを導入する方法を行いましたが、何度もつまずいてしまいました。
細かな設定ももう一度勉強し、ひとつひとつの解説もいつかやっていきたいです。
#参考文献
Docker + Rails + Puma + Nginx + MySQL
#エラー解消 rails newできない Running bundle update will rebuild your snapshot from scratch, using only the gems in your Gemfile, which may resolve the conflict.