人に説明するときに記事あると便利なので、開発環境向けのDockerfileとdocker-compose.ymlを書いておく。
Dockerfile
FROM ruby:3.0.0
WORKDIR /app
RUN curl -fsSL https://deb.nodesource.com/setup_14.x | bash -
RUN apt-get update && apt-get install -y \
git \
nodejs \
vim
RUN npm install -g yarn
RUN curl -sO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
&& apt install -y ./google-chrome-stable_current_amd64.deb \
&& rm google-chrome-stable_current_amd64.deb
RUN CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` \
&& curl -sO https://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip \
&& unzip chromedriver_linux64.zip \
&& mv chromedriver /usr/bin/chromedriver
- git: GitHubを参照してgemを入れるときに必要
- nodejs + yarn:
bin/rails assets:precompile
で必要
- vim:
bin/rails credentials:edit
で使う
- Chrome + chromedriver: System Test で必要
docker-compose.yml
version: "3.8"
services:
db:
image: postgres:12-alpine
volumes:
- postgres:/var/lib/postgresql/data
environment:
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:5-alpine
volumes:
- redis:/data
web: &web
build: .
image: app:1.0.0
stdin_open: true
tty: true
volumes:
- .:/app:cached
- bundle:/app/vendor/bundle
- node_modules:/app/node_modules
- rails_cache:/app/tmp/cache
- packs:/app/public/packs
- packs_test:/app/public/packs-test
tmpfs:
- /tmp
environment:
BUNDLE_PATH: "/app/vendor/bundle"
BOOTSNAP_CACHE_DIR: "/app/vendor/bundle"
WD_INSTALL_DIR: "/usr/local/bin"
HISTFILE: "/app/log/.bash_history"
EDITOR: "vi"
DATABASE_URL: "postgres://postgres:postgres@db:5432"
REDIS_URL: "redis://redis:6379/"
RAILS_MASTER_KEY:
depends_on:
- db
- redis
command: ["bin/rails", "server", "-b", "0.0.0.0"]
expose: ["3000"]
ports: ["3000:3000"]
user: root
working_dir: /app
worker:
<<: *web
command: ["bundle", "exec", "sidekiq"]
expose: []
ports: []
volumes:
postgres:
redis:
bundle:
node_modules:
rails_cache:
packs:
packs_test:
image: app:1.0.0
imageに名前とバージョンをつけておくことで、バージョンをインクリメントすると docker-compose run
のときに自動的にビルドが走る。
Dockerfileを変えたときにバージョンをインクリメントすることで、他の開発者が古いイメージを使い続けてしまう事を防ぐことができる。
stdin_open: true
tty: true
byebug
などでデバッグできるようにするため。
volumes:
- .:/app:cached
- bundle:/app/vendor/bundle
- node_modules:/app/node_modules
- rails_cache:/app/tmp/cache
- packs:/app/public/packs
- packs_test:/app/public/packs-test
Docker for Mac遅い問題の対処。
ホストとの同期を減らすことで若干マシになる。遅いけど。
worker:
<<: *web
command: ["bundle", "exec", "sidekiq"]
expose: []
ports: []
sidekiqを使う場合、基本的な設定はwebと同じなのでエイリアスを使う。
expose
, ports
はworkerで不要なので上書きする。
使い方
初回の環境構築
Dockerイメージを作成して、 bin/setup
を実行する。
$ docker-compose build
$ docker-compose run --rm web bin/setup
サーバの起動
$ docker-compose run --rm --service-ports web
実行すると http://localhost:3000 でアクセスできる。
$ docker-compose run --rm web bin/rails -T
テストの実行
$ docker-compose run --rm -e RAILS_ENV=test web bin/rails db:test:prepare
$ docker-compose run --rm -e RAILS_ENV=test web bin/rails test
コンテナ内で作業する
毎回コンテナの起動をすると遅いので、基本的にコンテナ内で作業した方が楽。
$ docker-compose run --rm web bash
root@b419978e89ec:/app# bin/rails --version
Rails 6.1.3
全てのvolumeを削除する
開発環境を一新したいときに使う。
$ docker-compose down --volumes
追加の説明
Dockerfileでbundle install
は不要なのか?
Dockerイメージのビルドでは不要です。
bin/setup
の実行で、マウントしてるvolumeにインストールされます。
なぜdocker-compose up web
で起動しないのか?
docker-compose up
で起動すると標準入力が使えなくなって、byebugでデバッグできなくなるため。
あと、コンテナを止めたときに稀にtmp/pids/server.pid
が残ることがある。*1
コマンドが長い
bibendi/dipを使うか、bashのエイリアスを使うと楽です。
開発用のイメージが大きい
alpineやmulti stage buildを使えば軽量化できるかもしれないですが、面倒だったので調べてないです。
開発環境用のDockerイメージが少し重くても、大して困らないため。