Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
773
Help us understand the problem. What are the problem?
@azul915

丁寧すぎるDocker-composeによるrails5 + MySQL on Dockerの環境構築(Docker for Mac)

はじめに

Dockerの勉強も兼ねてrailsのアプリをコンテナに作ろうとしたが環境構築にアホみたいに時間がかかった。
Dockerもrailsも(もはや初歩的なコマンドすら)不慣れなプログラマを救いたいので、手順を書きます。
あとDockerはこれからrailsエンジニアになる人が合わせて使えるようになっておけばスキルとして加点になるので(新しめの技術なので供給量的にも)、勉強のきっかけになればと。

この手順すらめんどくさいと思った方へ(2019-02-04追記)

何もない状態からrailsサーバーとMySQLのコンテナを立ててくれるシェル
※真面目に作りを意識しながらやった方が今後応用が効くようになるのでできるだけ読んで欲しいです...

環境(!!Rails5系で作成してます!!)

  • Mac OS
  • Ruby2.5.3
  • Rails5.2.2
  • MySQL5.7

-> Rails6系では、webpackが入った都合上、yarnのインストールが必要になります。

前提(2019-02-04追記)

 そもそもDockerコンテナを使うメリットの一つに周辺環境との依存を避けることができることが挙げられる。だが、ローカル(ホスト側)の任意の場所に、アプリを作っていくフォルダ/ファイルを作り、それらをDockerのコンテナ内で利用したり、逆にコンテナ内のフォルダ/ファイルをローカルで扱いたいケースがある。このような場合など、ローカル(ホスト側)の一部のフォルダ/ファイルをコンテナ内のフォルダ/ファイルと同期することをボリュームマウントするという。

mount-overview.png

 【画像・参考】さわって理解する Docker 入門 より

以上を踏まえて、ローカル(ホスト側)のアプリの作業フォルダをsampleApp(各自で命名してください)とし、コンテナ側をapp_nameとしている。app_nameDockerfiledocker-compose.ymlで使っているが、app_nameから変更しなくてよい。(コピペでOK)

ファイル構成(ホスト側つまりローカルが最終的にこういう構成になります)

sampleApp ---- Dockerfile
           |-- Gemfile
           |-- Gemfile.lock
           |-- README.md
           |-- Rakefile
           |-- app
           |-- bin
           |-- config ---- application.rb
           |           |-- boot.rb
           |           |-- cable.yml
           |           |-- credentials.yml.enc
           |           |-- database.yml
           |           |-- environment.rb
           |           |-- environments
           |           |-- initializers
           |           |-- locales
           |           |-- master.key
           |           |-- puma.rb
           |           |-- routes.rb
           |           |-- spring.rb
           |           |-- storage.yml
           |
           |-- config.ru
           |-- db
           |-- docker-compose.yml
           |-- lib
           |-- log
           |-- package.json
           |-- public
           |-- storage
           |-- test
           |-- tmp
           |-- vendor

【1】プロジェクトの作業ディレクトリを作成、移動

mkdirでディレクトリを作成してcdで移動

$ mkdir sampleApp
$ cd sampleApp

【2】作業ディレクトリでDockerfileを作成、中身の編集

主はvimで編集をしているが、touch Dockerfileして、エディタで編集してもOK。
Dockerfileは、Docker上で動作するコンテナの構成情報を記述するためのファイル
(この後【8】で実行してもらう、)docker-buildコマンドによって、Dockerfileに記述されたインフラの構成情報をもとにしてコンテナのもととなるイメージを作成する。

Dockerfileの注意点として、COPYADDをするときにホスト側(左側)は必ず(Dockerfileを置いてあるディレクトリからの)相対パスなので注意(初心者向けに明示的な書き方をした。)

## touch Dockerfile してから vi Dockerfileでもいいけど、カレントディレクトリ内に同じファイル名がなければ、作成&編集ができる
$ vi Dockerfile
Dockerfile
# コピペでOK, app_nameもそのままでOK
# 19.01.20現在最新安定版のイメージを取得
FROM ruby:2.5.3

# 必要なパッケージのインストール(基本的に必要になってくるものだと思うので削らないこと)
RUN apt-get update -qq && \
    apt-get install -y build-essential \ 
                       libpq-dev \        
                       nodejs           

# 作業ディレクトリの作成、設定
RUN mkdir /app_name 
##作業ディレクトリ名をAPP_ROOTに割り当てて、以下$APP_ROOTで参照
ENV APP_ROOT /app_name 
WORKDIR $APP_ROOT

# ホスト側(ローカル)のGemfileを追加する(ローカルのGemfileは【3】で作成)
ADD ./Gemfile $APP_ROOT/Gemfile
ADD ./Gemfile.lock $APP_ROOT/Gemfile.lock

# Gemfileのbundle install
RUN bundle install
ADD . $APP_ROOT

【3】Gemfileを作成、編集

 touch Gemfileで作成して、エディタで編集してもOK
GemfileはBunder用の設定ファイルでこれを元にgemの依存関係を示した、Gemfile.lockを作成する(【4】で空のGemfile.lockを作る)

# vimでGemfileの名前でファイル新規作成
$ vi Gemfile
Gemfile(コピペでOK)
source 'https://rubygems.org'
gem 'rails', '5.2.2'

【4】空のGemfile.lockを作成

$ touch Gemfile.lock

【5】docker-compose.ymlを作成、編集

ymlファイルを以下の例をコピペして作成、MYSQL_ROOT_PASSWORDMYSQL_DATABASEで、任意のパスワード(【7】で同じものを設定する)とデータベース名を設定

$ vi docker-compose.yml
docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"

  web:
    build: .
    command: rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/app_name
    ports:
      - "3000:3000"
    links:
      - db

【6】rails newを実行する

$ docker-compose run web rails new . --force --database=mysql --skip-bundle

【7】database.ymlを修正する

場所はここ -> /sampleApp/config/database.yml

## カレントディレクトリ(/sampleApp)配下を見てみると色々できていて、configも作成されている
$ ls -l

total 56
-rw-r--r--   1 author  staff   519  1 20 20:07 Dockerfile
-rw-r--r--   1 author  staff  2216  1 20 20:15 Gemfile
-rw-r--r--   1 author  staff     0  1 20 20:08 Gemfile.lock
-rw-r--r--   1 author  staff   374  1 20 20:15 README.md
-rw-r--r--   1 author  staff   227  1 20 20:15 Rakefile
drwxr-xr-x  10 author  staff   320  1 20 20:15 app
drwxr-xr-x   8 author  staff   256  1 20 20:15 bin
drwxr-xr-x  16 author  staff   512  1 20 20:15 config
-rw-r--r--   1 author  staff   130  1 20 20:15 config.ru
drwxr-xr-x   3 author  staff    96  1 20 20:15 db
-rw-r--r--   1 author  staff   261  1 20 20:09 docker-compose.yml
drwxr-xr-x   4 author  staff   128  1 20 20:15 lib
drwxr-xr-x   3 author  staff    96  1 20 20:15 log
-rw-r--r--   1 author  staff    67  1 20 20:15 package.json
drwxr-xr-x   9 author  staff   288  1 20 20:15 public
drwxr-xr-x   3 author  staff    96  1 20 20:15 storage
drwxr-xr-x  11 author  staff   352  1 20 20:15 test
drwxr-xr-x   5 author  staff   160  1 20 20:15 tmp
drwxr-xr-x   3 author  staff    96  1 20 20:15 vendor

## カレントディレクトリ(/sampleApp)にて
$ cd config
$ vi database.yml
database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password # docker-compose.ymlのMYSQL_ROOT_PASSWORD
  host: db # docker-compose.ymlのservice名

【8】Docker起動

/sampleApp/config/がカレントディレクトリなので、cd ..で一つ上の階層(/sampleApp)に移動すること

Why?

この後実行するdocker-composeコマンドはdocker-compose.ymlファイルを探して実行が進むので、そのディレクトリ(今回なら、/sampleApp)上で実行しなければならないから

$ docker-compose build # コンテナをビルド

# -dオプションをつけてバックグラウンド実行するとこの後新しいシェルを立ち上げる必要がなくなる
$ docker-compose up # コンテナの一斉起動

【9】DB作成

新しいterminalを開いて、/sampleAppで実行

$ docker-compose run web rails db:create

【10】ブラウザでlocalhost:3000にアクセスしてサーバーの起動を確認

スクリーンショット 2019-01-20 18.49.44.png

おまけ

 サーバーを止める

$ docker-compose down

Ctrl+Cで止めると、コンテナが残って次回起動時にエラーが出る
もしやっちゃったら、tmp/pids/server.pidを削除、再起動
再起動はdocker-compose upでできる

Dockerfileやdocker-compose.ymlの変更を反映、railsサーバーを再起動

$ docker-compose up --build

bundle installなどのコマンドを実行したい


#docker-compose run {サービス名} {任意のコマンド}
$ docker-compose run web bundle install

ローカルからMySQLコンテナに接続

$ mysql -u root -p -h localhost -P 3306 --protocol=tcp

追記(2019-01-24):ホスト側でDockerfileおよびdocker-compose.ymlとソースを分けたい方へ

ファイル構造(ホスト側)

sampleApp ---- Dockerfile
           |-- docker-compose.yml
           |
           |-- src -- |-- app
                      |-- bin
                      |-- config
                      |-- db
                      |-- lib
                      |-- log
                      |-- public
                      |-- storage
                      |-- test
                      |-- tmp
                      |-- vendor
                      |-- config.ru
                      |-- Gemfile
                      |-- Gemfile.lock
                      |-- README.md
                      |-- Rakefile

Dockerfile

# 19.01.20現在最新安定版
FROM ruby:2.5.3

# railsコンソール中で日本語入力するための設定 <- NEW
ENV LANG C.UTF-8

# RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
# /var/lib/apt/lists配下のキャッシュを削除し容量を小さくする <- NEW
RUN apt-get update -qq && \
    apt-get install -y build-essential \
                       libpq-dev \
                       nodejs \
    && rm -rf /var/lib/apt/lists/*

# 作業ディレクトリの設定
RUN mkdir /app_name
ENV APP_ROOT /app_name
WORKDIR $APP_ROOT

# gemfileを追加する
ADD ./src/Gemfile $APP_ROOT/Gemfile
ADD ./src/Gemfile.lock $APP_ROOT/Gemfile.lock

# gemfileのinstall
RUN bundle install
ADD ./src/ $APP_ROOT

docker-compose.yml

docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    volumes:
      - ./src/db/mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"

  web:
    build: .
    command: rails s -p 3000 -b '0.0.0.0'
    volumes:
      - ./src:/app_name
    ports:
      - "3000:3000"
    links:
      - db

何もない状態からrailsサーバーとMySQLのコンテナを立ててくれるシェル(2019-02-04追記)

ファイル構成

1. 任意の場所にアプリを作って行きたいフォルダ(作業ディレクトリ)を作成し、作ったフォルダ配下に移動
$ mkdir sampleApp
$ cd sampleApp
2. 以下のdocker-rails.shシェルをコピー、sampleAppフォルダ配下に置く
3. sampleAppフォルダ配下でシェルのファイルを実行
$ bash docker-rails.sh 
docker-rails.sh
#!/bin/bash

echo "docker pull ruby:2.5.3"
docker pull ruby:2.5.3

echo "docker pull mysql:5.7"
docker pull mysql:5.7

echo "docker images"
docker images

# make Dockerfile
cat <<'EOF' > Dockerfile
FROM ruby:2.5.3
ENV LANG C.UTF-8
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs && rm -rf /var/lib/apt/lists/*
RUN gem install bundler
WORKDIR /tmp
COPY src/Gemfile Gemfile
COPY src/Gemfile.lock Gemfile.lock
RUN bundle install
ENV APP_HOME /app_name
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
COPY . $APP_HOME
EOF


# make 'src' directory and cd 'src' directory
mkdir src && cd src


# make Gemfile
cat <<'EOF' > Gemfile
source 'https://rubygems.org'
gem 'rails'
EOF

# make Gemfile.lock()
touch Gemfile.lock


# cd ../
cd ../


# make docker-compose.yml
cat <<'EOF' > docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    volumes:
      - ./src/db/mysql_data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_DATABASE=root
    ports:
      - "3306:3306"
  web:
    build: .
    command: rails s -p 3000 -b '0.0.0.0'
    volumes:
      - ./src:/app_name
    ports:
      - "3000:3000"
    links:
      - db
    tty: true
    stdin_open: true
EOF

echo "docker-compose run web rails new . --force --database=mysql --skip-bundle"
docker-compose run web rails new . --force --database=mysql --skip-bundle

# cd 'src'
cd src

# fix Gemfile
echo "fix Gemfile(uncoment mini_racer)"
cat Gemfile | sed "s/# gem 'mini_racer'/gem 'mini_racer'/" > __tmpfile__
cat __tmpfile__ > Gemfile
rm __tmpfile__


# cd ../
cd ../


docker-compose build

# cd src/
cd src/


# fix config/database.yml
echo "fix config/database.yml"
cat config/database.yml | sed 's/password:$/password: root/' | sed 's/host: localhost/host: db/' > __tmpfile__
cat __tmpfile__ > config/database.yml
rm __tmpfile__

# cd ../
cd ../


echo "docker-compose run web rake db:create"
docker-compose run web rake db:create

echo "docker-compose up"
docker-compose up
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
773
Help us understand the problem. What are the problem?