先々月に公開したこちらの翻訳記事の実践編ということで。試行錯誤しているうちにRailsが6.0.1になりました。
Docker Desktop for Macについて
これまではピュアな環境を求めてParallels Desktop for MacのUbuntu VM上でDockerを使っていたのですが、久しぶりにDocker Desktop for Macを使ってみると速度や使い勝手が随分よくなっていて驚きました。
- Docker Desktop for Macの方がUbuntu VMのDockerよりビルドが速い(体感ですが)
- ただしEvil Martiansの記事にもあるように、docker-composeでボリュームに
:cached
を記述しておかないとDocker Desktop for Macで遅くなります
- ただしEvil Martiansの記事にもあるように、docker-composeでボリュームに
- 今はdmgファイルをダウンロードしてアプリケーションフォルダにドロップするだけでインストール完了できる
Ubuntuだと基本的にsudo
を打たないとDockerが使えないのと(回避方法は一応ありますが)、macOSとの間のレイヤが増えるつらみの方が大きくなってきたので、Docker Desktop for Macでやることにしました😅。
環境
- macOS: 11.2.3(Big Sur)
- Docker Desktop for Mac: 3.2.2(61853)
- Docker: 20.10.5
- Docker-compose: 1.28.5
- Dockerhubにログインしておく
- (既存のDockerがあれば削除しておく)
- Rails: 6.1.3.1
- Ruby: 3.0.1
- Git: 2.31.0
- git-flowを使う前提
- dipをインストールする
本記事でのDocker操作は全面的にEvil Martians謹製のdipを使っています。dipの説明は割愛しますが、とてもよかったので別記事にしたいと思います。
追記(2019/12/04): 書きました↓
リポジトリ
今回のサンプルを以下のリポジトリに置きました。
プロジェクトディレクトリ
├── .dockerdev
│ ├── .bashrc
│ ├── .psqlrc
│ ├── Aptfile
│ └── Dockerfile
├── .env(ダミー)
├── dip.yml
└── docker-compose.yml
変更の方針
- Evil Martiansの設定からの変更は最小限とし、できるだけ汎用性を高める
- docker-compose内の
image
名は自分のプロジェクトに合わせてリネームし、:1.0.0
は残す
- docker-compose内の
- Evil Martians流でやるとイメージのサイズが1GBになるので軽量化する
- その代わり基本的なツールは自分で補わないといけない😅
- SidekiqとRedisは使わないのでdocker-compose.ymlから削除
- dip.ymlは多少カスタマイズする
- .psqlrcも入れておく
- BundlerはRubyに同梱されるようになったのでDockerfileのBundlerのインストールスクリプトは含めなかった。
- 9bd609でDockerfileに追加されたfreedesktop.org.xmlのダウンロードスクリプトは含めなかった。詳しくは以下をご覧ください。
週刊Railsウォッチ(20210329前編)特集: Rails更新版の臨時リリースとmimemagic gemのGPL問題
変更後のDockerfile
ARG RUBY_VERSION
# 後述
FROM ruby:$RUBY_VERSION-slim-buster
ARG PG_MAJOR
ARG NODE_MAJOR
ARG YARN_VERSION
# 共通の依存関係
RUN apt-get update -qq \
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
build-essential \
gnupg2 \
curl \
less \
git \
shared-mime-info \
&& apt-get clean \
&& rm -rf /var/cache/apt/archives/* \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
&& truncate -s 0 /var/log/*log
# PostgreSQLをsources listに追加
RUN curl -sSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& echo 'deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list
# NodeJSをsources listに追加
RUN curl -sL https://deb.nodesource.com/setup_$NODE_MAJOR.x | bash -
# Yarnをsources listに追加
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo 'deb http://dl.yarnpkg.com/debian/ stable main' > /etc/apt/sources.list.d/yarn.list
# 依存関係をインストール
COPY ./.dockerdev/Aptfile /tmp/Aptfile
RUN apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get -yq dist-upgrade && \
DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends \
libpq-dev \
postgresql-client-$PG_MAJOR \
nodejs \
yarn=$YARN_VERSION-1 \
$(grep -Ev '^\s*#' /tmp/Aptfile | xargs) && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
truncate -s 0 /var/log/*log
# bundlerとPATHを設定
ENV LANG=C.UTF-8\
GEM_HOME=/bundle\
BUNDLE_JOBS=4\
BUNDLE_RETRY=3
ENV BUNDLE_PATH $GEM_HOME
ENV BUNDLE_APP_CONFIG=$BUNDLE_PATH\
BUNDLE_BIN=$BUNDLE_PATH/bin
ENV PATH /app/bin:$BUNDLE_BIN:$PATH
# RubyGemsをアップグレードして必要なバージョンのbundlerをインストール
RUN gem update --system &&\
gem install rails &&\
mkdir -p /app
WORKDIR /app
Dockerfileの変更のポイント
- イメージを
ruby:2.6.5
からruby:3.0.1-slim-buster
に変更- イメージが軽くなる代わりに、そのままだと
curl
やping
などの基本的なパッケージも入らないので、apt-getでインストールするかAptfileに書いておきます
- イメージが軽くなる代わりに、そのままだと
curl
を実行するRUN
コマンドをまとめてイメージの肥大化を防ぐgem install rails
を追加
これでイメージは1GBから671MBに半減しました。もっと減らしたいならAlpine Linuxベースのイメージを使う手もあります。
Dockerのマルチステージビルドもやってみたかったのですが、手間の割にあまり報われない気がしたのと、Evil Martians流からあまり離れたくなかったので見送りました。
変更後のdocker-compose.yml
version: "3.8"
services:
app: &app
build:
context: .
dockerfile: ./.dockerdev/Dockerfile
args:
RUBY_VERSION: "3.0.1"
PG_MAJOR: "13"
NODE_MAJOR: "12"
YARN_VERSION: "1.22.4"
image: yourapp_docker:1.0.0
tmpfs:
- /tmp
backend: &backend
<<: *app
stdin_open: true
tty: true
volumes:
- .:/app:cached
- rails_cache:/app/tmp/cache
- bundle:/bundle
- node_modules:/app/node_modules
- packs:/app/public/packs
- .dockerdev/.psqlrc:/root/.psqlrc:ro
- .dockerdev/.bashrc:/root/.bashrc:ro
environment:
- NODE_ENV=development
- RAILS_ENV=${RAILS_ENV:-development}
- DATABASE_URL=postgres://postgres:postgres@postgres:5432
- BOOTSNAP_CACHE_DIR=/bundle/bootsnap
- WEBPACKER_DEV_SERVER_HOST=webpacker
- WEB_CONCURRENCY=1
- HISTFILE=/app/log/.bash_history
- PSQL_HISTFILE=/app/log/.psql_history
- EDITOR=vi
depends_on:
- postgres
- webpacker
env_file: .env
runner:
<<: *backend
command: /bin/bash
ports:
- "3000:3000"
- "3002:3002"
rails:
<<: *backend
command: bundle exec rails server -b 0.0.0.0
ports:
- "3000:3000"
postgres:
image: postgres:13
volumes:
- .psqlrc:/root/.psqlrc:ro
- postgres:/var/lib/postgresql/data
- ./log:/root/log:cached
environment:
- PSQL_HISTFILE=/root/log/.psql_history
- POSTGRES_HOST_AUTH_METHOD=trust
ports:
- 5432
env_file: .env
webpacker:
<<: *app
command: ./bin/webpack-dev-server
ports:
- "3035:3035"
volumes:
- .:/app:cached
- bundle:/bundle
- node_modules:/app/node_modules
- packs:/app/public/packs
environment:
- NODE_ENV=${NODE_ENV:-development}
- RAILS_ENV=${RAILS_ENV:-development}
- WEBPACKER_DEV_SERVER_HOST=0.0.0.0
volumes:
postgres:
bundle:
node_modules:
rails_cache:
packs:
docker-compose.ymlの変更のポイント
- redisなど、自分の使わないサービスを削除した
- 認証情報は.envファイルに含め、.gitignoreに追加した
- そのため
env_file: .env
をyamlに2箇所追加した - (リポジトリの.envは空にしてあります)
- そのため
- credentialの暗号化機能はまだ使っていません
たとえ空であっても本当は.envをリポジトリに入れたくありませんでしたが、すぐ試せるようにしたかったのでした。
補足
このdocker-compose.ymlはローカル開発環境の構築のみを想定しています。Evil Martiansもそのように作っています。
PostgreSQLの接続文字列はdocker-compose.ymlに以下のように丸ごと埋め込まれています↓ので、db/database.ymlを開発用に設定する必要はありませんし、db/database.ymlにdevelopment環境用の設定を加えても効きません(ハマりました😅)。db/database.ymlを設定するのはCIやproductionぐらいになると思います。
DATABASE_URL=postgres://postgres:postgres@postgres:5432
docker-compose.ymlのimage名のyourapp_docker
の部分は適宜自分のプロジェクト名に変えてください。
追記(2021/03/27)
PostgreSQLを13にアップグレードしたところ、従来のパスワードなしログインが効かなくなったため、docker-compose.ymlに以下を追加しました。この設定はローカルのdevelopment以外では使わないでください。
- POSTGRES_HOST_AUTH_METHOD=trust
セットアップ
- dipをインストールする(homebrewでもできます)
gem install dip
git clone git@github.com:hachi8833/rails_docker_like_evilmartians.git
でリポジトリをcloneしてディレクトリに移動する- docker-compose.ymlの
yourapp_docker
は自分のプロジェクト名に変更する(本記事では変更していません) -
git checkin
してコミット -
dip compose build
でビルド
$ dip compose build
# 略
Successfully tagged yourapp_docker:1.0.0
dip sh
でコンテナにログインする
$ dip sh
Creating network "rails_docker_like_evilmartians_default" with the default driver
Creating volume "rails_docker_like_evilmartians_postgres" with default driver
Creating volume "rails_docker_like_evilmartians_bundle" with default driver
Creating volume "rails_docker_like_evilmartians_node_modules" with default driver
Creating volume "rails_docker_like_evilmartians_rails_cache" with default driver
Creating volume "rails_docker_like_evilmartians_packs" with default driver
root@7b09aea79b9f:/app#
以下はDockerコンテナ内部での作業です。
yarn -v
、ruby -v
、bundle -v
、which rails
が実行できることを確認rails new
に好みのオプションを付けて実行
なおbundle exec
は不要です。
今回は以下のオプションにしました。アプリ名はapp
で固定されます。Webpackerもまとめてセットアップされます。
rails new . --database=postgresql --skip-active-storage --skip-action-mailer --skip-active-job --skip-action-cable --skip-action-mailbox --skip-action-text --skip-turbolinks --skip-sprockets --skip-spring --skip-bootsnap --webpacker --webpack=vue
root@7b09aea79b9f:/app# rails new . --database=postgresql --skip-active-storage --skip-action-mailer --skip-active-job --skip-action-cable --skip-action-mailbox --skip-action-text --skip-turbolinks --skip-sprockets --skip-spring --skip-bootsnap --webpacker --webpack=vue
# 略
success Saved lockfile.
success Saved 12 new dependencies.
info Direct dependencies
├─ vue-loader@15.9.6
├─ vue-template-compiler@2.6.12
└─ vue@2.6.12
info All dependencies
├─ @vue/component-compiler-utils@3.2.0
├─ consolidate@0.15.1
├─ de-indent@1.0.2
├─ he@1.2.0
├─ merge-source-map@1.1.0
├─ prettier@1.19.1
├─ vue-hot-reload-api@2.3.4
├─ vue-loader@15.9.6
├─ vue-style-loader@4.1.3
├─ vue-template-compiler@2.6.12
├─ vue-template-es2015-compiler@1.9.1
└─ vue@2.6.12
Done in 6.40s.
Webpacker now supports Vue.js 🎉
- 環境によっては以下も実行して、bundlerの余分なメッセージを抑制する
bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java
- 使われていないvendorディレクトリを
rm -rf vendor
で削除 exit
でDockerをいったん抜けるgit checkin
する
起動前の設定
- config/environments/development.rbに以下を追加する
config.hosts << "localhost"
config.web_console.whitelisted_ips = '0.0.0.0/0'
Rails 6からはconfig.hostを明示的に指定する必要があります(ウォッチ20190401)。
また、Dockerで開発する場合はおそらくwhitelisted_ips
の制約も解除が必要になります。
- 参考
追記(2021/03/27): dip provision
を実行する前にGemfileのtestブロックに以下を追記し、dip bundle install
を実行してrexml gemをインストールしてください。
gem 'rexml', '~> 3.2', '>= 3.2.4'
参考: Rails 6.1, Ruby 3.0.0: tests error as they cannot load rexml - Stack Overflow
dip provision
を実行してdevelopmentとtestの空データベースを作成- (dip.yamlをそれ用にカスタマイズしています)
- データベース名は
app_development
とapp_test
で固定
$ dip provision
# (略)
== Preparing database ==
Created database 'app_development'
== Installing dependencies ==
The Gemfile's dependencies are satisfied
== Preparing database ==
== Removing old logs and tempfiles ==
== Restarting application server ==
== Installing dependencies ==
The Gemfile's dependencies are satisfied
== Preparing database ==
Created database 'app_test'
== Removing old logs and tempfiles ==
== Restarting application server ==
- 念のため
dip minitest
でminitestを実行
$ dip minitest
Starting rails_docker_like_evilmartians_postgres_1 ... done
Run options: --seed 59169
# Running:
Finished in 0.000523s, 0.0000 runs/s, 0.0000 assertions/s.
0 runs, 0 assertions, 0 failures, 0 errors, 0 skips
git checkin
でコミット
いよいよ起動
dip rails s
でRailsを起動して、ブラウザでhttp://localhost:3000/を開く
できた!
$ dip rails s
Starting rails_docker_like_evilmartians_postgres_1 ... done
=> Booting Puma
=> Rails 6.0.1 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.0 (ruby 2.6.5-p114), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
後は好きに進めます。dip ls
すればdipのサブコマンド一覧が表示されます。
作業が終わったらdocker-compose down
でコンテナを終了します。
参考: 後からプロジェクトに参加する人の作業
- Git、Docker for Mac、git-flow、dipなどをセットアップ
- リポジトリを
git clone
する dip compose build
dip bundle install
dip yarn install --check-files
- .envに秘密鍵を入れるのであれば、.gitignoreに.envを追加する(必須)
- データベースにseedデータを入れる(略)
Dockerfileを改定した場合は、docker-compose.ymlのimage名のタグにあるバージョン番号を適宜更新します。
おたより発掘
techrachoさん、無限に知見を流しててマジすごい / 1件のコメント https://t.co/opsZ4CJ5s7 “Rails 6のDocker開発環境構築をEvil Martians流にやってみた” https://t.co/jdyh5IrARK
— igaiga (@igaiga555) November 21, 2019
更新情報