はじめに
個人開発をしていると、アプリ開発を進めている内に環境構築の手順などを忘れてしまって、後から「このアプリの環境構築手順ってどうやるんだっけ?」となる事があると思います(PC変えたときとか、README.md書くときとか)。
後から友達が開発へ加わることになった場面などでも、環境構築の手順を説明するのが大変だったりします。
そのような悩みを解決する方法の1つが、VS Codeのdevcontainerの拡張機能になります。
devcontainerの概要
devcontainerはVS CodeのDev Containers
という拡張機能を使って立ち上げる、開発用のDockerコンテナです(公式ドキュメント)。
devcontainerには以下のようなメリットやデメリットがあります。
メリット
- コンテナを立ち上げるだけで、同じ開発環境を再現することが出来る
- 開発環境をコンテナ化することで、異なるホストマシンでも同じように動作させることが出来ます
- ※コンテナもホストマシンの影響を受けるので、絶対的にあらゆる環境で同一の動作をする訳ではありません
- 異なるホストマシンでも同じような動作をするため、コンテナを立ち上げるだけで開発に関わる人が同じ環境を再現することが容易にできます
- 開発環境をコンテナ化することで、異なるホストマシンでも同じように動作させることが出来ます
- VS Codeの拡張機能も開発メンバーで統一することが出来る
- VS Codeの拡張機能をdevcontainerを利用することで、統一することが出来ます。予め何の拡張機能をインストールするかを記載しておけるので、後から開発に参加した人が一々拡張機能をインストールしていくという手間が省けます
- ローカル環境が汚れない
- コンテナで開発環境を立ち上げるため、ホストマシンが汚れる事はありません
デメリット
以下のデメリットですが、2つとも確証を持って挙げているデメリットではありません。個人的な体感や予想で記載しています。
- ホストマシンで直接動かすよりも動きが重い(かもしれない)
- 比較データを持っているわけではないですが、ホストマシンで操作するときに比べて動きが重いと感じます。(時々ファイルの保存にラグを感じますが、私のPCだけかもしれません)
- 自分用にインストールした開発ツールがリビルドすると消えてしまう?
- 自分用に
apt-get install
でインストールしていた開発ツール(tigとか、treeとか)はリビルドすると消えてしまうため、開発コンテナのDockerfileが書き換わる度に、自分用のツールはinstallし直さなければいけないかもしれません- ※本格的なチーム開発での利用をしたことがないため、偏見で記載しています。もしかしたら自分用の開発ツールを保持したままリビルドする方法があるかもしれません
- 自分用に
Railsの環境構築の手順の紹介
動作環境
- Windows11 Home
- WSL Version 2.0.9.0
- Ubuntu 22.04.3 LTS
- VS Code: 1.73.0
- Docker version 24.0.7
- Docker Compose version v2.21.0
構築する開発環境
devcontainerの開発手順について記載していきますが、Rails × MySQLの構築手順となります。
1. VS Codeの拡張機能のインストール
2. 開発したいアプリのディレクトリ作成
- アプリのディレクトリを作成してそのプロジェクトをVS Codeで開きます
- ※
code .
等でプロジェクトを開き直すのは、作成したアプリのディレクトリをVS Codeで開かないとVS Code側がどのプロジェクトのdevcontainer/.devcontainer.json
を参照すれば良いか分からなくなるからです
- ※
- 今回のsample用アプリのディレクトリは以下で作成し、VS Codeで開き直します
mkdir sample_devcontainer && cd sample_devcontainer && code .
3. 必要なファイルを用意し、devcontainerを立ち上げる
devcontainer.jsonの作成
-
mkdir .devcontainer
で.devcontainerディレクトリを作成します - .devcontainerディレクトリ配下にdevcontainer.jsonファイルを作成し、以下の内容を記載します
{
"name": "Rails Devcontainer",
// 今回はdocker-composeを利用するため、dockerComposeFileでパスを指定する
"dockerComposeFile": [
"docker-compose.yml"
],
// docker-compose.ymlで指定する、開発コンテナのサービス名
"service": "app",
// 自分が作業する場所を指定する
"workspaceFolder": "/workspaces/sample_devcontainer",
// コンテナ内で使う拡張機能
"customizations": {
"vscode": {
"extensions": [
"Shopify.ruby-lsp",
"misogi.ruby-rubocop",
"ms-azuretools.vscode-docker"
]
}
}
}
docker-compose.ymlの作成
- 続いて.devcontainer配下にdocker-compose.ymlを作成します
-
env_file
でMySQLのDB作成時に利用する環境変数を読み込む設定をします- 環境変数参照にすることで、DBに設定しているパスワードなどが外部に漏れづらくなるので、env_file参照に設定します
- volumesではアプリのディレクトリをコンテナ内にマウントする設定をします
- マウントをすることで、ホストマシンとコンテナ内のファイルが同期し、ファイルの編集内容がどちらにも反映されるようになります
- docker-compose.ymlは.devcontainer内に作成しているため、マウント対象は1階層上を指定します
version: '3'
services:
app:
env_file:
- ../.env
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspaces/sample_devcontainer:cached
command: sleep infinity # 開発コンテナが勝手にダウンしない為に設定する
ports:
- 3000:3000
depends_on:
- db
db:
image: mysql:8.0
env_file:
- ../.env
volumes:
- db-store:/var/lib/mysql
ports:
- 3306:3306
volumes:
db-store:
Dockerfileの作成
- 次に.devcontainer配下にDockerfileを作成します
- RUNコマンドはすべてvscodeユーザーとして実行しています
- 理由として、Dockerfile内では何も指定しないとRootユーザーで実行するのですが、Rootユーザーが作成したファイルなどは一般ユーザーにアクセス権限がなく、アプリ起動時のエラーに繋がるからです
- Dockerイメージにマイクロソフトのイメージを利用すると、開発コンテナ作成が楽になります
- Microsoft社の公式イメージを使用しない場合、Dockerfile内で一般権限のユーザーを作成したり、Gitの設定をしたりなど、大変な作業が必要になります。そのため、devcontainerを利用する際には以下のDocker Hubから使用言語に該当するイメージを利用した方が良いと思います
- Docker Hubへのリンク
- 利用できるRubyイメージのリリースタグはこちらに記載してあります
- Dockerイメージを選ぶ際は公式には以下のように記載されているので、詳細なバージョンタグを設定ない方が良いかもしれません
-
In general, we recommend using the major release version of this tag to avoid breaking changes while still taking fixes and content additions as they land. E.g. 0-16-bullseye. See the appropriate "History" or "All tags" link under repos and tags get a full list of available versions for the image.
- ただ、メジャーバージョンやマイナーバージョンまでの指定だと、いつの間にかイメージ内のRubyのバージョンが変わっていたりするので、どちらを選ぶかは好みだと思います
-
- Microsoft社の公式イメージを使用しない場合、Dockerfile内で一般権限のユーザーを作成したり、Gitの設定をしたりなど、大変な作業が必要になります。そのため、devcontainerを利用する際には以下のDocker Hubから使用言語に該当するイメージを利用した方が良いと思います
# ↓ 現時点のデフォルトイメージ
FROM mcr.microsoft.com/devcontainers/ruby:1.1-3.3-bullseye
# ↓ 詳細にリリースタグを指定する場合
# FROM mcr.microsoft.com/devcontainers/ruby:1.1.1-3.3-bullseye
RUN apt update && \
apt-get install --no-install-recommends -y \
build-essential \
default-libmysqlclient-dev \
mariadb-client \
libvips \
pkg-config \
git
RUN su vscode -c "gem install rails:7.1.3"
RUN su vscode -c "/usr/local/rvm/bin/rvm fix-permissions"
WORKDIR "/workspaces/sample_devcontainer"
RUN bundle config set --local path vendor/bundle
envファイルの作成
- 最後に、環境変数を設定する.envファイルと、リポジトリ作成時のsampleになる.env.sampleをルート直下に作成します
MYSQL_ROOT_PASSWORD=root-user-password
DEV_DB_NAME=your-development-db-name
TEST_DB_NAME=your-test-db-name
PROD_DB_NAME=your-production-db-name
DB_HOST=db
BINDING=0.0.0.0
MYSQL_ROOT_PASSWORD=root-root
DEV_DB_NAME=DevDB
TEST_DB_NAME=TestDB
PROD_DB_NAME=ProdDB
DB_HOST=db
BINDING=0.0.0.0
- 上の手順が終わったら
Ctrl + Shift + P
で検索パレットを開き、Reopen in Container
をクリックします
- コンテナの立ち上げが終わると、開発コンテナ内にrailsやrubyがインストールされていることを確認出来ます
vscode ➜ /workspaces/sample_devcontainer $ rails -v
Rails 7.1.3
vscode ➜ /workspaces/sample_devcontainer $ ruby -v
ruby 3.2.3 (2024-01-18 revision 52bb2ac0a6) [x86_64-linux]
4. Railsプロジェクトを作成する
-
rails new
コマンドでRailsプロジェクトを作成します。私はデータベースをMySQL、CSSをTailwindで作成したいため以下コマンドを実行します- オプションについては
rails new -h
で確認できます
- オプションについては
rails new . -d mysql --css tailwind
- 次にdatabesa.ymlを以下のように修正します
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
password: <%= ENV["MYSQL_ROOT_PASSWORD"] %>
host: <%= ENV["DB_HOST"] %>
development:
<<: *default
database: <%= ENV["DEV_DB_NAME"] %>
test:
<<: *default
database: <%= ENV["TEST_DB_NAME"] %>
production:
<<: *default
database: <%= ENV["PROD_DB_NAME"] %>
- gemのインストール先を
vendor/bundle
に指定しているため、gitignoreの修正を行います
- /.bundle
+ /vendor/bundle
+ !/.env.sample
- DBを作成し、必要なgemをインストールする
bin/setup
- tailwindをビルドする
rails tailwindcss:build
上までの手順でサーバーを立ち上げる環境が整いました。以下のコマンドでサーバーを立ち上げ、localhost:3000にアクセスすると、以下の画面が見えると思います。
rails s
最後に
今回はdevcontainerの開発環境構築手順について説明しました。ただ、私自身がまだDockerやRails、DBの知識が不足している部分があるため、上記手順について不備や改善点等ございましたら、教えて頂けますと幸いです。