はじめに
久しぶりに個人開発をするにあたってDockerで環境構築をしようと思いましたが、
- 転職時のポートフォリオに開発環境で使ったときは、使えそうなコードを見つけ、コードの意味を調べて導入するも、あらためて見るとあまり理解できていない
- 業務でもすでに準備されているDockerfileなどにより環境構築し、日頃はコンテナを起動して開発を進めるだけなので理解が深まっていない
ということに気がつき、危機感を覚えました。
というわけで、今回は自分で考えながらDockerでの環境構築に取り組んでみました。
その過程を記事にすることで頭の整理をするとともに、同じような状況の人の気づきになってくれれば嬉しく思います。
ちなみに、当面の目標はRails6 + Vue3 + PostgreSQLの開発環境をDockerで構築することですが、いきなりあれもこれも手を出すことはせず、まずはRails6 + PostgreSQLに絞ることにしました。
(2022.9.18追加)
Rails6 + Vue3 + PostgreSQLの開発環境をDockerで構築するまでが完了したので、続きを記事にまとめました。
目次
1. 開発環境
2. 今回のゴール
3. この記事で扱わない内容
4. 本編
4-1. 事前準備
4-2. アプリを作成
4-3. yarnをインストール
4-4. 再びアプリを作成
4-5. データベースの設定
4-6. localhost:3000にアクセス
4-7. scaffoldを使って動作確認
5. まとめ
1. 開発環境
- macOS Monterey 12.3.1
- Docker 20.10.13
- docker-compose 1.29.2
2. 今回のゴール
Dockerで以下の開発環境を構築すること
- Ruby on Rails 6.1
- Ruby 3.0
- PostgreSQL
3. この記事で扱わない内容
- イメージやコンテナといったDockerの基本的事項について
- コードの詳細な説明について
4. 本編
今回、構築したいRails + PostgreSQLの開発環境については、Dockerの公式サイトにチュートリアルがあるので、こちらをベースに進めていきます。
ただ、このチュートリアルはRuby 2.5、Rails 5とバージョンが古いため、それを今回のゴールに定めたバージョンに変えて構築することがこの記事のポイントです。
4-1. 事前準備
まずは作業ディレクトリを準備します。
$ mkdir docker-sample
$ cd docker-sample
公式チュートリアルに沿って、以下のファイルを作業ディレクトリ内に作成します。
この時、導入したいバージョンを忘れずに指定します。
# ここでバージョンを修正
FROM ruby:3.0
RUN apt-get update -qq \
&& apt-get install -y nodejs postgresql-client
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
source 'https://rubygems.org'
# ここでバージョンを修正
gem 'rails', '~> 6.1'
# 何も書きません
#!/bin/bash
set -e
# Remove a potentially pre-existing server.pid for Rails.
rm -f /app/tmp/pids/server.pid
# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
version: "3.9"
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/app
ports:
- "3000:3000"
depends_on:
- db
4-2. アプリを作成
上記ファイルを準備したら、以下のコマンドでアプリを作成します。
$ docker compose run --no-deps web rails new . --force --database=postgresql
このコマンドについて、簡単に解説しておきます。
docker compose run --no-deps web
は、docker-compose.ymlで定義したwebコンテナで、以後のコマンド(rails new
)を実行するという意味です。
--no-deps
オプションは、リンクしているコンテナ(今回であればdepends_on
で指定されているdbコンテナ)を起動しないというものです。
rails new . --force --database=postgresql
でアプリを作成します。
.
は現在のディレクトリにアプリを作成するということを示しています。
--force
は同名のファイルが存在する場合に上書きするというオプションです。
今回は事前に準備したGemfileとGemfile.lockが現在のディレクトリにあるので、上書きされます。
--database=postgresql
は見たまんまですが、データベースにPostgreSQLを指定しています。
さて、ここで早速ですが、エラーがでました。内容は以下のとおりです。
Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/
yarnをインストールしろと怒られました。
そういえば、Rails6からはWebpackerがデフォルトと聞いたことがあります。(参考)
このWebpackerでyarnが必要となるので、怒られているようです。
4-3. yarnをインストール
早速、yarnをインストールしたいので、エラー文にも載っている公式サイトでインストール方法を調べます。
何やらnpmを使う方法と使わない方法があるようです。
今のDockerfileではnpmはインストールしていません。
以後、yarnを使うのであれば、このためだけにnpmをインストールする必要はないと考え、今回は使わない方法で進めることにしました。
npmをインストールする方法も試したところ、うまくいきました。
イメージやコンテナを作り直して、あれこれ気軽に試せるところもDockerの魅力ですね!
npmを使わないyarnのインストール方法を確認するためには、OSを選択する必要があるようです。
docker hubを見にいきましたが、すぐには見つけらませんでした。
見つけられないなら、直接コンテナに入って確認することはできないだろうかと思い、OS情報のありかを調べてみます。
どうやら/etc/os-release
にOS情報が保存されているようです。
それでは、OS情報を調べる目的だけなので、今回のベースイメージであるRuby 3.0
の最小限のDockerfileを準備し、作成したコンテナでOS情報を調べてみます。
準備したDockerfileはこちら
FROM ruby:3.0
CMD ["/bin/bash"]
CMD ["/bin/bash"]
により、コンテナを起動させたらbashが起動します。
それでは、以下のコマンドでイメージの作成、コンテナの起動をします。
$ docker image build -t os_check .
$ docker container run --rm -it os_check
-t
オプションは後で管理しやすいようにこのイメージに名前をつけているだけなので、それほど気にしなくて大丈夫です。
無事にコンテナが起動したので、先ほどのOS情報の入っているファイルを見てみます。
$ cat /etc/os-release
出力結果はこちら
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
このベースイメージのOSはLinuxディストリビューションのDebianであることがわかりました。
これで安心してyarnのインストールが進められます。
せっかくなので、このままコンテナ内でyarnインストールのコマンドを実行してみましょう。
$ 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 -qq
$ apt-get install -y yarn
$ yarn -v
1.22.19
ばっちりインストールできているようなので、Dockerfileに反映させます。
FROM ruby:3.0
RUN 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 -qq \
&& apt-get install -y nodejs yarn postgresql-client
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
4-4. 再びアプリを作成
再度、以下のコマンドを実行してみます。
$ docker compose run --no-deps web rails new . --force --database=postgresql
今度こそRailsアプリが作成できました!
Gemfileが書き換えられたので、イメージをbuildしておきましょう。
$ docker compose build
4-5. データベースの設定
再び、公式チュートリアルに戻り、データベースの設定をします。
作成したRailsアプリのconfig/database.ymlを以下のとおり修正します。
default: &default
adapter: postgresql
encoding: unicode
host: db
username: postgres
password: password
pool: 5
development:
<<: *default
database: app_development
test:
<<: *default
database: app_test
4-6. localhost:3000にアクセス
まずは、以下のコマンドでコンテナを起動させ、データベースを作成します。
$ docker compose up -d
$ docker compose run web rails db:create
さて、これで準備は完了です。
localhost:3000にアクセスしてみましょう。
お馴染みのページが迎えてくれました!やった!
4-7. scaffoldを使って動作確認
ちゃんと動いてくれるのかscaffoldを使ってサクッと確認してみます。
先ほどのコンテナは起動させたままで以下のコマンドを実行します。
$ docker compose exec web bash
$ rails generate scaffold book title:string
$ rails db:migrate
localhost:3000/booksにアクセスすると以下の画面が表示されます。
New Bookからデータを作成し、その後の編集や削除も問題なくできました。
5. まとめ
今回は公式チュートリアルに少し変更を加えて、Dockerで開発環境を構築をしてみました。
この変更により発生したエラーを調べつつ解消するという過程が、今後に活きてくるのではないかと考えています。
実際、開発をスタートしてから「あー、この部分が足りなかったなー」と感じることもあると思います。
そんな時は今回のように必要なライブラリなどを一つずつ確認しながら対応していきたいと思います。
また、記事にまとめるにあたって、イメージ、コンテナを作っては壊し、作っては壊しを何度も繰り返しました。
Dockerではこういった作っては壊しが手軽にできるので「このコマンドを使ってみよう」「このライブラリをインストールしてみよう」という実験がとてもやりやすく、この点もDockerの魅力の一つだなと感じました。(ローカルでは元に戻すことが難しいので、不安になります…)
途中、脇道に逸れて、Ruby3.0-alpine
など別のベースイメージを使ったらどうなるのかなども試してみました。
もともとインストールされているライブラリが違ったり、ライブラリをインストールするためのコマンドが違ったりと、今まで意識したことのなかった違いも発見できて、いい勉強となりました。
同時に、同じRuby3.0を使うとしても、どのイメージが最適かといった選定ができるようになるには、まだまだ勉強が必要だなと感じました。
さて、今回の記事はここまでです。
長い記事にお付き合いいただき、ありがとうございました。
次はRails6 + Vue3 + PostgreSQLの開発環境構築を目指して、引き続きDockerで遊んでみようと思います!