はじめに
現在、Railsを学習しているものです。プログラミング学習を始めて約5ヶ月が経ちました。その中で特に苦手意識があるのが環境構築です。今回は、Dockerを活用してRailsの環境構築を行ったので、その備忘録としてこの記事をまとめました。
自分のステータスは以下の通りです
- 仮想環境を使うと環境構築が楽になると記事で読んだことがある。
- Dockerという名前を聞いたことがあるが、実際に使ったことはない。
という状態で、ずっと学習したいと思っていましたが、なかなか手がつけられませんでした。
- RailsはProgateを3周し、基本を押さえたため、自分の手元で開発を進めたい。
- 環境構築でまた足踏みするのは避けたい。
- せっかくなのでDockerも合わせて勉強してみたい。
という考えで学習を始めました。ほぼ自分のメモ書きとして本記事を作成していますが、どなたかの参考になれば幸いです。
仮想環境とは
仮想環境とは、パソコンやサーバーなど1つのハードウェア上で、仮想的に構築された別の環境のことです。言い換えれば、コンピューターの中に「もう1つのコンピューター」を作り出すようなイメージです。
仮想環境を利用することで、開発環境を本体のPCとは独立して管理できるため、トラブルの原因を切り分けやすくなります。
Docker
概要をとりまとめると以下の通りです。
- コンテナ型仮想環境を作成、実行、管理するためのプラットフォーム。
- Dockerのソフトウェアを使って素早くコンテナを起動し、色々なアプリケーションを実行することができる。
- Dockerの設定ファイルを共有すれば、異なる環境(PCやサーバー)で簡単に仮想環境を再現できる。
例えば、Rubyのアプリケーションを活用したい場合は、Rubyがインストールされたコンテナを起動すれば、即座にRubyアプリケーションを実行して動作を確認することができます。このように、用途に合わせてコンテナを起動すれば、様々なアプリケーションを実行できるのが特徴です。
メリット
- プログラムの実行環境を素早く立ち上げることができる。
- PCで開発したプログラムを、サーバーで動かす場合も差異がうまれにくく、トラブルになりにくい。
- 設定ファイルを共有することで、メンバー間で同じ環境を立ち上げることができる。
- 仮想環境内にパッケージをインストールするだけなので、PCに直にインストールする必要がないため、PCの環境をごちゃごちゃ汚さずに済む。
用語
Dockerイメージ
Dockerコンテナを作成するための雛形となるものです。アプリケーションやライブラリなど、実行に必要なもの一式をまとめています。完成したアプリケーションをDockerイメージとして保存し、別のサーバーに移すことで、同じ環境を再現することができます。
Dockerコンテナ
Dockerイメージを元に作成される仮想環境のことです。単に「コンテナ」と呼ばれることもあります。イメージから何度でも同じコンテナを作成できるため、開発やテストの効率が向上します。
勉強になった記事を紹介します。
環境構築
全体の流れは以下の通りです。
- Railsアプリケーションのベースを作成
- Railsアプリケーションを実行するためのDockerfileを作成
- docker composeで開発環境を構築
- docker composeコマンドによる環境の起動
Railsアプリケーションのベースを作成
Ruby3.2.2がインストールされたコンテナを起動してシェルを起動
任意のディレクトリ(今回はrails-practice
)に移動し、以下のコマンドを実行します。これはDockerを使用して Ruby の Alpine Linux ベースイメージをもとに、コンテナを作成しコマンド起動してます。
docker run --rm -ti -v ./rails-practice:/app ruby:3.2.2-alpine sh
コマンド構成は下記の通りです。
docker run
新しい Docker コンテナを作成して実行します。
--rm
コンテナの実行が終了した際に、コンテナを自動的に削除します。一時的な作業に便利です。
-ti
インタラクティブモードを有効にし、標準入力を開いたままにします。これにより、コンテナ内でコマンドを入力して操作できます。
-v ./rails-practice:/app
ローカルディレクトリ ./rails-practice
をコンテナ内の /app ディレクトリにマウントします。これにより、ローカルのファイルとコンテナ内のファイルを同期させることが可能です。
ruby:3.2.2-alpine
Ruby 3.2.2 を含む Alpine Linux ベースの軽量イメージを使用します。
sh
コンテナ内でシェル (sh) を起動します。この状態でコンテナ内を操作できます。
#
(プロンプト)が表示されていると思います。これは、上記コマンドでシェルを起動しているため、現在コンテナに繋がっている状態です。コマンドを実行するとLinuxコンテナでのコマンド実行を意味します。
Railsでアプリケーションを作成する際に必要なパッケージのインストール
起動しているシェルに以下のコマンドを実行します。これは、Railsに必要なパッケージのインストールをしています。
apk update
apk add git g++ make mysql-dev
Railsのインストール
RubyGemシステム(gemそのもの)のアップデートし、Railsのバージョンを指定しインストールします。
gem update --system
gem install rails -v 7.0.6
プロジェクト作成
以下の通り Railsコマンドを実行し、入力したアプリケーション名と同名のフォルダが作成され、その中に開発に必要なフォルダやファイルが用意されます。
rails new /app
ls -la /app/
上記コマンドで、コンテナ内に作成されたフォルダ構成を確認することができます。
また、このコンテナ内のフォルダと現在自分がいるカレントディレクトリ(rails-practice
)は同期されています。これは、コンテナ作成時に-v ./rails-practice:/app
を実行し、マウントしているためです。
ここまででRailsを動かすための土台部分が完成です。
Railsアプリケーションを実行するためのDockerfileを作成
実は、手動で実装した上記コマンドは、dockerfile
というものを作れば、今までの作業を全てスクリプト化し、セットアップすることが可能です。スクリプト化することにより、チーム内や別の環境で同じ構成を簡単に再現できます。
上記コマンドをdockerfile
に書き直すと以下の通りです。
# ベースとして使用するイメージ名(DockerHub:公式からダウンロードされる)
FROM ruby:3.2.2-alpine
# 利用可能なパッケージのリストを更新するコマンドを実行
RUN apk update
# パッケージをインストールするコマンドを実行
RUN apk add g++ make mysql-dev tzdata gcompat
# コンテナを起動した時の作業ディレクトリを/appにする
WORKDIR /app
# PC上のGemfile を .(/app)にコピー
COPY Gemfile .
COPY Gemfile.lock .
# bundle installでGemfileに記述されているgemをインストール
RUN bundle install
source 'https://rubygems.org'
gem 'rails', '7.0.6'
docker build
でイメージを作成し、docker run
で命令(FROM
,RUN
など)が実行され、Railsの構築は完了です。
ですが、まだRailを動かすことができません。なぜなら、RailsにDBが接続されていないためです。次回手順でDBと接続作業を実施します。
docker composeで開発環境を構築
上述の通り、Railsのコンテナのみではアプリケーションとして成立していないため、DBとの接続が必要です。そこで活用するのが、docker compose
です。
docker compose
は、複数のDockerコンテナを定義、接続し、一括管理するツールです。
設定ファイルdocker-compose.yml
を用いることで、サービス、ネットワーク、マウントの設定を一元管理できます。
version: '3'
services:
web:
build: .
command: sh -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
db:
image: mysql:8.0
volumes:
- db-volume:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
volumes:
db-volume:
上記は、RailsアプリケーションとMySQLデータベースの連携を簡単に管理する設定です。以下に各部分の説明を簡潔にまとめます。
-
バージョン指定
version: '3'
Docker Composeのバージョンを指定。 -
servicesセクション
web:
build: .
command: sh -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
build: .
現在のディレクトリにあるDockerfileを使ってRailsアプリ用のイメージをビルドします。
command
作成したコンテナに対して、どんなコマンドを実行するのか指定します。今回は、Railsサーバー起動コマンドを指定し、サーバーのPIDファイ(tmp/pids/server.pid)を削除してからサーバーを起動します。
volumes.
現在のディレクトリ(.)をコンテナの/appにマウントしてます。これにより、ローカルで編集したRailsコードが即座にコンテナ内で反映されます。
ports
コンテナのポート3000をホストのポート3000に公開。これにより、ブラウザからアクセスすることができます。
depends_on
dbサービス(MySQLコンテナ)に依存関係を持たせます。MySQLが準備される前にRailsが起動しないようにしております。
db:
image: mysql:8.0
volumes:
- db-volume:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: password
image
MySQL 8.0の公式イメージを使用します。
volumes
db-volume:/var/lib/mysql:永続化ストレージを設定します。MySQLデータがコンテナ停止後も保持されます。
environment
環境変数でMySQLの設定を指定します。今回は、MySQLのルートユーザーのパスワードを指定。
3.volumes
セクション
volumes:
db-volume:
db-volume
コンテナ外にデータを保存したいため、ボリュームを新規作成します。これにより、Dockerの管理下のフォルダとして自動で作成されるため、コンテナを削除してもDBに影響を及ぼしません。
docker composeコマンドによる環境の起動
以上より、Railsの環境構築をする準備がととのったため、環境の起動をします。
docker compose build
これにより、docker-compose.ymlに定義したbuildの定義に基づいてDockerイメージがビルドされます。
docker image ls
>>rails-practiceが作成
Dockerイメージのリストを表示します。特別名前を指定しない限り、イメージ名は、フォルダ名である”rails-practice”とサービス名であるweb
という名前に基づいてイメージ名が自動的に決定されます。
docker compose up
docker-compose.ymlに定義された内容に基づいて、コンテナを起動されました。ブラウザでlocalhost:3000
を送信すると無事Railsの初期画面が表示されます。
以上より、Gemfile``docekerfile``docker-compose.yml
があればRailsの環境構築は完了です。
補足
下記の通り、config
フォルダにあるdatabase.yml
ファイルのDB接続先を指定する必要があります。
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: password
host: db
docker compose exec web rails db:create
web
サービスのコンテナ上でdbを作成するコマンドを実行します。
最後に
今回、Dockerを使ってRailsの開発環境を構築する手順を学びました。仮想環境の概念からDockerの仕組み、そしてRailsとMySQLを組み合わせた環境を作り上げるプロセスを経験することで、これまで苦手だった環境構築に対する不安が少し解消されたように感じます。
特に、Dockerを活用することで「一度設定すれば、いつでもどこでも同じ環境を再現できる」便利さを実感しました。開発環境が安定することで、本来の目的であるアプリケーション開発に集中できるようになります。この学びを活かして、次は実際のアプリケーション開発に挑戦していきたいと思います。
この記事は私自身の備忘録としてまとめたものですが、同じように環境構築でつまずいている方や、Dockerを初めて学ぼうとされている方の一助になれば幸いです。
今後も学習を続け、さらに技術力を高めていきたいと思います。それでは、最後までお読みいただきありがとうございました!