はじめに
現在、就職活動中のプログラミング初学者です。
開発環境にDockerを取り入れる為、いろいろ勉強して自分用のメモとしてまとめておりましたが、折角なら同じ初学者の方の役に立てればと思い投稿させて頂きます。既に多くの方がDockerの環境構築に関する記事を書かれており、そういった記事を参考にさせて頂きながら、メモとしてまとめていましたので、内容はそんなに目新しものではありません。予めご了承ください。また、誤った表現などがありましたらご指摘頂けると幸いです。
開発環境
- Ruby 2.6.3
- Rails 5.2.3
- MySQL 5.7
- MacOS 10.15.5
前提条件
- Dockerhubのアカウントを作成している。
- Docker for Macをインストールしている。
- Dockerの基礎はある程度抑えている。
Dockerの基本的なことはこちらの記事が参考になります。
いまさらだけどDockerに入門したので分かりやすくまとめてみた
対象読者
今回は開発環境を構築することを目標とする為、Dockerに関する基礎的な部分はある程度抑えている方とします。
Railsの開発環境構築
DockerでRailsの開発環境を構築するには以下のファイルが必要になります。
- Dockerfile
- Gemfile
- Gemfile.lock
- docker-compose.yml
1.作成するアプリ名のディレクトリを作成する。
まずは、上記のファイルを作成するディレクトリを作成します。
#ターミナル
$ mkdir my-app
2.作成したディレクトリに移動する。
$ cd my-app
3.Dockerfileを作成する。
1.で作成したディレクトリ内にDockerfileを作成します。
$ touch Dockerfile
Dockerfileとは?
Dockerでは、dockerhubで公開されているimageを元にコンテナを起動することができるが、必要なパッケージや各種の設定を含んだDocker imageを自分で作成して使用したい場合が出てくる。その場合にDockerfileを用意して、それを元にDocker imageを作成することができる。
Dockerfileにはベースのimageに対して実行する内容を記述する。
4.Dockerfileに記述する。
# ベースイメージ 今回はrubyのimage。
FROM ruby:2.6.3
# 必要なパッケージのインストール
RUN apt-get update -qq && \
apt-get install -y build-essential \
libpq-dev \
nodejs
# 作業ディレクトリの作成、設定
RUN mkdir /my-app
#作業ディレクトリを指定している
WORKDIR /my-app
# ホスト側(ローカル)のGemfileを追加する(ローカルのGemfileは別途事前に作成しておく)
COPY ./Gemfile /my-app/Gemfile
COPY ./Gemfile.lock /my-app/Gemfile.lock
# Gemfileのbundle install
RUN bundle install
COPY . /my-app
5.Gemfileを作成する。
$ touch Gemfile
6.Gemfileに記述する。
source 'https://rubygems.org'
gem 'rails', '5.2.3'
7.空のGemfile.lockを作成する。
$ touch Gemfile.lock
8.docker-compose.ymlを作成する。
$ touch docker-compose.yml
Docker Composeとは?
Dockerでは1つのコンテナには、1つのアプリケーションのみを入れておき、複数のコンテナを組み合わせてサービスを構築するという方法が推奨されている。
Docker Composeは、複数のコンテナで構成されるアプリケーションについて、Docker imageのbuildや各コンテナの起動・停止などをより簡単に行えるようにするツール。
docker-compose.ymlとは?
Docker Composeを使用する際に必要となるファイルのこと。
docker-compose.ymlには以下の内容を定義します。
- Docker imageをbuildするための情報(使用するDockerfile、image名など)
- コンテナ起動するための情報(ホストとの共有ディレクトリ設定やポートフォワードなどの起動オプションなど)
- 使用するDockerネットワーク など
9.docker-compose.ymlに記述する。
version: '3' # Dockerのバージョンを指定
services:
db: # データベースサーバ用のコンテナの設定を記述
image: mysql:5.7 # コンテナで使用するイメージ名を記述
environment:
MYSQL_ROOT_PASSWORD: password # 任意のパスワードを設定
MYSQL_DATABASE: root # 任意のデータベース名を設定
ports:
- "3306:3306" # ホストの3306ポートとコンテナの3306ポートを接続する。
volumes:
- ./db/mysql/volumes:/var/lib/mysql #ホストの./db/mysql/volumesをコンテナ内の/var/lib/mysqlにマウントする。Dockerのコンテナと、ローカルを同期している。コンテナを削除してもデータは永続化する。
web: # アプリケーションサーバ用のコンテナの設定を記述
build: . # docker-compose.ymlと同じ階層にあるDockerfileを使ってimageをbuildするための記述
command: bundle exec rails s -p 3000 -b '0.0.0.0' # コンテナ立ち上げ時に起動するコマンド。railsを実行する。
volumes:
- .:/my-app # 作業ディレクトリをコンテナ内の/my-appにマウントする。
ports:
- "3000:3000" # ホストの3000ポートとコンテナの3000ポートを接続する。
depends_on:
- db # 依存関係を表している。dbが起動してからwebが起動するという意味。
10.コンテナを起動し、コンテナ内でrails newを実行する。
$ docker-compose run web rails new . --force --database=mysql --skip-bundle
run
コマンドは、imageの構築から、コンテナの構築・起動まで行います。
また、run
コマンドを介して引数で指定したサービスのコンテナ内でコマンドを実行できます。つまり、ここでは生成されたコンテナ内でrails new
を行っています。
--force
オプションはファイルが存在する場合に上書きで作成するためのオプション。
--database=mysql
オプションは使用するデータベースの指定をするためのオプション。
--skip-bundle
オプションはbundle install
をスキップするためのオプション。
11.database.ymlを修正する。
rails new
で作成されたデータベースの接続設定ファイルにはホスト名とパスワードが設定されていません。railsアプリケーションがデータベースに接続できるようにするため、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名
12.buildを実行する。
$ docker-compose build
ここでbuildを実行する理由は10.で実行したコマンドによりGemfileの内容が書き換わっている為です。
13.Dockerを起動する。
$ docker-compose up -d # docker-compose.ymlを参照してコンテナが一斉起動する。
注意点としてここで実行するdocker-compose
コマンドはdocker-compose.ymlを元に実行が進むので、docker-compose.ymlがあるディレクトリ上で実行する必要があります。
14.データベースを作成する。
docker-compose run web
をコマンドの先頭につけることでコンテナ内でコマンドを実行できるので、
$ docker-compose run web rails db:create
を実行すれば、データベースが作成できます。
要は、docker-compose run web
に続けていつものローカルで開発している時のコマンドが使えます。
では、localhost:3000に接続してみましょう。
以下の画面が表示されれば完了です。
gemを入れてbundle installしてみる。
開発環境が整ったので試しにgemを入れてbundle installしてみます。
gem 'devise'
$ docker-compose run web bundle install
そして、
$ docker-compose run web rails g devise:install
しかし以下のようなエラーが出ました。
Could not find bcrypt-3.1.15 in any of the sources
Run `bundle install` to install missing gems.
bundle install
したはずなのに。。。
これは12.のところと同じ現象です。つまり、ローカルで書き換えたGemfileがコンテナ内のGemfileに反映されていない。ここでは再度、docker-compose build
を行う必要があります。理由はDockerfileを見れば分かります。
COPY ./Gemfile /my-app/Gemfile
COPY ./Gemfile.lock /my-app/Gemfile.lock
Dockerfile内でimageをbuildする際にローカル側のGemfileをコンテナ側にコピーしていました。ですから、現状ローカルのGemfileの変更はコンテナのGemfileには反映されていない訳です。これを反映させる為に、再度docker-compose build
を行う(imageをbuildし直す)必要があるという訳です。
では、再度docker-compose build
を実行します。
$ docker-compose build
もう一度、エラーが出たコマンドを試します。
$ docker-compose run web rails g devise:install
今度は上手く行きました。
しかし、gemを入れるたびに毎回docker-compose build
するのは面倒臭い。。。
という訳で、毎回docker-compose build
をしなくてもいいようにこちらの記事を参考にさせてもらい、docker-compose.yml
を編集します。
docker-composeでRailsのGemを更新する時、docker buildするのを回避したい
version: '3'
services:
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: root
ports:
- "3306:3306"
volumes:
- ./db/mysql/volumes:/var/lib/mysql
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/my-app
- gem_data:/usr/local/bundle # ローカルのgem_dataをコンテナ内の/usr/local/bundleにマウントする。
ports:
- "3000:3000"
depends_on:
- db
volumes: # 上記のvolumesのgem_dataはローカルのものを使うことを指定している。
gem_data:
これで、gemをインストールするたびにdocker-compose build
をしなくてもよくなりました。
binding.pryをしたい時
docker-compose.ymlに以下を記述します。
web:
tty: true
stdin_open: true
SequelProでデータベースを可視化する。
私はローカルで開発を行う際、SequelProを使用してデータベースを可視化していましたが、コンテナの仮想環境下では現状SequelProでデータベースを可視化することはできません。
docker-compose.ymlを以下の様に書き換えSequelProでデータベースを可視化できるよう設定していきます。
services:
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: root
ports:
- "4306:3306" # ホストの4306ポートをコンテナ内の3306ポートに接続するよう書き換える。
volumes:
- ./db/mysql/volumes:/var/lib/mysql
次に、sequelpro起動時のモーダル内のタブを標準タブに切り替え、下記の通りに入力します。
名前: defaultのまま
ホスト: 127.0.0.1 # 自分自身を表すIPアドレス
ユーザー名: root # database.ymlに記載のユーザー名
パスワード: password # database.ymlに記載のパスワード
データベース: 空欄のまま
ポート: 4306 # docker-compose.ymlに記載したlocal側のports番号
これでdocker環境下でもデータベースが可視化できるようになります。
参考記事・参考動画
今回Dockerを学習するにあたり、多くの方の記事を参考にさせて頂きました。
ありがとうございました。
docker-compose コマンドまとめ
docker-compose up とか build とか start とかの違いを理解できていなかったのでまとめてみた。
既存のRailsアプリをDockerコンテナで動かす方法+sequel proによるDBコンテナ可視化
Dockerを使用したRails開発①(環境構築)
【rails環境構築】docker + rails + mysql で環境構築(初心者でも30分で完了!)