既存アプリの開発環境をDockerに。色々とハマりましたが、そこも含めて書いて行きます。
##環境
Ruby:2.6.5
Rails:5.2.4
Mysql:5.7
OS: macOS Mojave 10.14.5
##ディレクトリ構成
sampleApp ---- Dockerfile
|-- docker-compose.yml
|-- app
|-- bin
|-- config
|-- database.yml
既存アプリのルート直下にDockerfile
、docker-compose.yml
を作成しました。
##うまくいったやり方
# app_nameの部分はそのままでOK
FROM ruby:2.6.5
RUN apt-get update -qq && \
apt-get install -y build-essential \
libpq-dev \
nodejs
RUN mkdir /app_name
ENV APP_ROOT /app_name
WORKDIR $APP_ROOT
ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock
RUN gem install bundler
RUN bundle install
ADD . $APP_ROOT
version: '3'
services:
db:
image: mysql:5.7
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_DATABASE: root
MYSQL_ALLOW_EMPTY_PASSWORD: 1
ports:
- "3305:3306"
web:
build:
context: .
dockerfile: Dockerfile
command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
tty: true
stdin_open: true
depends_on:
- db
ports:
- "3000:3000"
volumes:
- .:/app_name
- ~/.ssh:/root/.ssh
volumes:
mysql_data:
default: &default
adapter: mysql2
encoding: utf8mb4
charset: utf8mb4
collation: utf8mb4_general_ci
pool: 5
#以下の3行が重要
username: root
password:
host: db
#
timeout: 5000
development:
<<: *default
database: sample_app_development #sample_appの部分は、アプリ名に応じて修正
test:
<<: *default
database: sample_app_test #sample_appの部分は、アプリ名に応じて修正
$ docker-compose build
$ docker-compose up -d
$ docker-compose run web rails db:create
$ docker-compose run web rails db:migrate
http://localhost:3000/ にアクセスして、アプリのトップページが表示さればひとまず成功。
##遭遇したエラー
###.env
ファイル内のスペース
HOGE_KEY = age053nf3g3jk0 #×
HOGE_KEY=age053nf3g3jk0 #◯
###RUN gem install bundler
RUN gem install bundler #この行が無いとエラーがでたので追加した
RUN bundle install
ADD . $APP_ROOT
###MYSQL_ALLOW_EMPTY_PASSWORD: 1
version: '3'
services:
db:
image: mysql:5.7
environment:
MYSQL_DATABASE: root
MYSQL_ALLOW_EMPTY_PASSWORD: 1 #この行が無いとエラーがでたので追加した
###db:createが通らない
ここでめっちゃハマった。まじきつかった。
docker-compose down --volumes
からのdocker-compose up -d --build
で解決する的な情報があって、試してみたけどうまくいかず。
docker-compose.yml
のenvironment
と、database.yml
の値をゴニョゴニョして(今の形にして)
$ docker-compose down --rmi all
$ docker-compose build
$ docker-compose up -d
$ docker-compose run web rails db:create
で解決。
###ローカルの変更が反映されない
docker-compose.yml
のweb>volumes
の箇所が間違っていた。
Dockerfile
内で作成したディレクトリapp_name
を記述することで解決。
###コンテナを削除するたびにDBのデータが消える
名前付きボリュームを設定して解決。これでdown
→up
した時、以前のデータが残ったままになりました。
version: '3'
services:
db:
image: mysql:5.7
volumes: #ここと
- mysql_data:/var/lib/mysql
.
.
volumes: #ここ!
mysql_data:
DBのデータを永続化する方法には、
・名前つきボリューム
・匿名ボリューム
・ローカルのディレクトリのマウント、
の3つがあって、名前つきボリュームが一番良いらしい。
Dockerのデータを永続化!Data Volume(データボリューム)の理解から始める環境構築入門
Docker、ボリューム(Volume)について真面目に調べた
###変な感じでコンテナを停止しちゃった後、再開できなくなる時がある
rails s
の前にPIDを削除するように設定する
command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
###ローカルからデータベースに接続できない
3306のポートは、ローカルのmysqlで埋まっているので、ポートを3305に変えて接続
version: '3'
services:
db:
image: mysql:5.7
volumes:
- mysql_data:/var/lib/mysql
environment:
MYSQL_DATABASE: root
MYSQL_ALLOW_EMPTY_PASSWORD: 1
ports:
#- "3306:3306"
- "3305:3306"
###RSpecのSystem Specが動かない
Dockerfile
にchromeをインストールする記述を追加(不要な人もいるかもなので、記事冒頭の「うまくいった方法」には載せてないです。)
RUN apt-get update && apt-get install -y unzip && \
CHROME_DRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` && \
wget -N http://chromedriver.storage.googleapis.com/$CHROME_DRIVER_VERSION/chromedriver_linux64.zip -P ~/ && \
unzip ~/chromedriver_linux64.zip -d ~/ && \
rm ~/chromedriver_linux64.zip && \
chown root:root ~/chromedriver && \
chmod 755 ~/chromedriver && \
mv ~/chromedriver /usr/bin/chromedriver && \
sh -c 'wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -' && \
sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list' && \
apt-get update && apt-get install -y google-chrome-stable
RUN mkdir /app_name
.
.
###Better Errorsが使えない
#以下を追加
if Rails.env.development?
BetterErrors::Middleware.allow_ip! "0.0.0.0/0"
end
dockerで立ち上げたrailsサーバでもBetter Errorsを使えるようにする
###ssh接続ができなくなった
volumes
に~/.ssh:/root/.ssh
を追記→パーミッションを変更
version: '3'
#省略
web:
#省略
volumes:
- .:/app_name
- ~/.ssh:/root/.ssh #この行を追加
volumes:
mysql_data:
ローカルで設定した秘密鍵のパーミッションは引き継がれないので、手動で変更する必要があります。
$ docker-compose exec web /bin/bash
$ cd /root/.ssh
$ chmod 600 id_rsa
##その他のサンプル
Rails6 + Postgres
FROM ruby:2.6.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
#Rails6はyarnが必要!!
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn
RUN mkdir /app_name
ENV APP_ROOT /app_name
WORKDIR $APP_ROOT
ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock
RUN gem install bundler
RUN bundle install
ADD . $APP_ROOT
version: '3'
services:
db:
image: postgres
volumes:
- psgl_data:/var/lib/postgresql/data
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: password
ports:
- 5433:5432
web:
build:
context: .
dockerfile: Dockerfile
command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
tty: true
stdin_open: true
depends_on:
- db
ports:
- "3000:3000"
volumes:
- .:/app_name
volumes:
psgl_data:
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
#以下の3行が重要
host: db
username: root
password: password
#check_yarn_integrity: true
check_yarn_integrity: false
DBのデータをローカルにマウントする場合
version: '3'
services:
db:
image: postgres
volumes:
- ./dbdata:/var/lib/postgresql/data #ローカルのdbdataディレクトリにデータを保存して同期
environment:
POSTGRES_USER: root
POSTGRES_PASSWORD: password
ports:
- 5434:5432
web:
build:
context: .
dockerfile: Dockerfile
command: /bin/sh -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
tty: true
stdin_open: true
depends_on:
- db
ports:
- "3000:3000"
volumes:
- .:/app_name
#トップレベルのvolumesは不要
##参考
- 丁寧すぎ
るDocker-composeによるrails5 + MySQL on Dockerの環境構築(Docker for Mac) - Inject host's SSH keys into Docker Machine with Docker Compose
##最後に
改善できるところがあったら指摘してもらえると嬉しいです。