最近、RailsのDocker開発環境をチューニングしたので、備忘録です。
構成
基本
- M1 Mac
- Ruby 3.1.2
- Rails 7.0.4
- Node 16系
- Postgresql
その他
- webpacker(Rails7から引退したみたいなので、そのうち剥がしたい)
- solargraphもdocker
- rubocopもdockerにしたいけどしてない。
説明
こちらの記事を見て、volume に gem をインストールするよう bundler に設定しました。
https://zenn.dev/aldagram_tech/articles/110bc79925d41b
bundle install前に設定
bundle config set --local path /usr/local/bundle
docker-compose.yml
bundle:/usr/local/bundle
ファイル
Dockerfile
FROM ruby:3.1.2-alpine
ENV LANG=ja_JP.UTF-8
ENV TZ=Asia/Tokyo
ENV RAILS_ENV="development"
ENV NODE_ENV="development"
ENV ROOT=/app
WORKDIR $ROOT
COPY Gemfile Gemfile.lock $ROOT
RUN apk --update --no-cache add --no-cache -t .build-dependencies \
build-base \
libxml2-dev\
libxslt-dev \
&& apk add --no-cache python3 make g++\
# M1 Macで必要
gcompat \
bash \
file \
libpq \
libxml2 \
libxslt \
nodejs \
postgresql-dev \
tini \
tzdata \
yarn \
graphviz \
msttcorefonts-installer \
fontconfig \
font-bitstream-type1 \
ghostscript-fonts \
ttf-freefont\
imagemagick \
git \
&& gem install bundler \
&& bundle config set --local path /usr/local/bundle \
&& bundle install -j4
RUN update-ms-fonts \
&& fc-cache -f \
&& rm -rf /var/cache/*
COPY . $ROOT
RUN yarn install --check-files \
&& bundle exec rails webpacker:compile
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
docker-compose.yml
webpackerを別で作ることで、ホットリロードできるのでこのような構成にしました。
(Rails7では標準っぽいので、Webpacker使ってるプロジェクト向きです。)
version: "3.7"
services:
db:
image: postgres:latest
container_name: db
ports:
- '5432:5432'
expose:
- 5432
environment:
POSTGRES_DB: api
POSTGRES_USER: postgresql
POSTGRES_PASSWORD: postgresql
POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
TZ: "Asia/Tokyo"
volumes:
- db:/var/lib/postgresql/data:cached
app:
container_name: app
command: ash -c "rm -f tmp/pids/server.pid && ./bin/rails s -p 3000 -b '0.0.0.0'"
build:
context: .
dockerfile: Dockerfile
ports:
- 3000:3000
volumes:
- .:/app:delegated
- node_modules:/app/node_modules
- tmp:/app/tmp
- bundle:/usr/local/bundle
tmpfs:
- /tmp
environment:
RAILS_ENV: development
NODE_ENV: development
DB_HOST: db
DB_NAME: rails-app
DB_USER: postgresql
DB_PASSWORD: postgresql
WEBPACKER_DEV_SERVER_HOST: webpacker
tty: true
stdin_open: true
depends_on:
- db
- webpacker
- solargraph
webpacker:
container_name: wds
build: .
command: ./bin/webpack-dev-server
volumes:
- .:/app:delegated
- node_modules:/app/node_modules
environment:
RAILS_ENV: development
NODE_ENV: development
WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
ports:
- "3035:3035"
solargraph:
container_name: solargraph
build: .
command: bundle exec solargraph socket --host=0.0.0.0 --port=7658
volumes:
- .:/app:delegated
- bundle:/usr/local/bundle
ports:
- "8091:7658"
volumes:
db:
bundle:
node_modules:
tmp:
entrypoint.sh
bundle check || bundle install --jobs 4
とすることで、docker-compose up時に、bundle installが必要なら、自動でしてくれます。
#!/bin/bash
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /app/tmp/pids/server.pid
echo "bundle install..."
bundle config set --local path /usr/local/bundle \
&& bundle check || bundle install --jobs 4
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
Makefile
毎回docker-compose up とか入力するの面倒なので、Makefile使ってます。
個人では、.zhsrcのalias使って、dc
で実行できるようにしてますが、チーム開発用にMakefileです。
alias dc='docker-compose'
make up
でrailsを起動するようにしてますが、合わせてattachして、byebugも使えるようにしてます。
※docker-compose.ymlのappのところで、以下を定義する必要あり。
tty: true
stdin_open: true
.PHONY: init up bundle migrate seed rspec lint-all rubocop slim-lint brakeman rails_best_practices
rubocop=bundle exec rubocop -A
brakeman=bundle exec brakeman --rails7 -q -o brakeman.html
rails_best_practices=bundle exec rails_best_practices
slim-lint=bundle exec slim-lint app/views/
init:
docker-compose build --no-cache
docker-compose run --rm app bin/setup
make seed
up:
docker-compose up -d && docker attach $$(docker-compose ps -q app | sed -n 1p)
bundle:
docker-compose run --rm app bundle install
migrate:
docker-compose run --rm app bin/rails db:apply
seed:
docker-compose run --rm app bin/rails db:seed
rspec:
docker-compose run --rm app bundle exec rspec && open coverage/index.html
lint-all:
docker-compose run --rm app bash -c '${rubocop} && ${brakeman} && ${rails_best_practices}'
rubocop:
docker-compose run --rm app $(rubocop)
slim-lint:
docker-compose run --rm app $(slim-lint)
brakeman:
docker-compose run --rm app $(brakeman)
rails_best_practices:
docker-compose run --rm app ${rails_best_practices}
終わりに
もう少しチューニングできるような気はしてますが、今の所これで落ち着いてます。
改善点などあれば、ぜひ教えていただきたいです!