0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rails API開発環境の構築 - Devcontainer + Docker Composeで再現性の高い環境を作る

Posted at

概要

Webアプリケーション開発において、チーム間での環境差異やホスト環境の汚染を防ぐため、DevcontainerとDocker Composeを組み合わせた開発環境を構築します。

今回は、Rails 7.2 API-only + PostgreSQL構成で、開発環境と本番環境の両方をDockerで管理するテンプレートを紹介します。

なぜ Devcontainer + Docker Compose を使うのか?

VSCodeのRemote Containers(devcontainer)機能を使えば、以下のようなメリットがあります。

  • 開発環境の再現性が高い - チームメンバー全員が同じ環境で開発できる
  • ホスト環境を汚さない - Ruby、Node.js、PostgreSQLなどをホストにインストール不要
  • 複数のプロジェクト間で環境を分離できる - バージョン違いのRailsプロジェクトも共存可能
  • 開発環境と本番環境の構成を統一できる - Dockerfileを共通化し、差分のみ管理

ディレクトリ構成例

個人開発ではモノレポを活用しているため、.devcontainerディレクトリ下にbackendディレクトリを作成し、そこにDockerfile等を置いています。

project-root/
├── .devcontainer/
│   └── backend/                # 開発環境用設定
│       ├── devcontainer.json   # VSCode設定
│       ├── docker-compose.yml  # 開発用compose
│       ├── Dockerfile          # 開発用Dockerfile
│       └── .env                # 環境変数(Git管理外)
│
└── backend/
    ├── docker/                 # 本番環境用設定
    │   ├── docker-compose.yml  # 本番用compose
    │   ├── Dockerfile          # 本番用Dockerfile
    │   └── .env                # 本番環境変数(Git管理外)
    ├── app/
    ├── config/
    ├── Gemfile
    └── Gemfile.lock

開発環境の構築例

Dockerfile(開発用)

.devcontainer/backend/Dockerfile:

FROM ruby:3.4.7-bookworm

ENV DEBIAN_FRONTEND=noninteractive \
    RAILS_ENV=development \
    TZ=Asia/Tokyo \
    LANG=C.UTF-8 \
    LC_ALL=C.UTF-8

# Railsで必要な基本ツール+pg用ヘッダ
RUN apt-get update && apt-get install -y --no-install-recommends \
    bash \
    git \
    curl \
    tzdata \
    ca-certificates \
    tree \
    build-essential \
    pkg-config \
    libpq-dev \
    nodejs \
    postgresql-client \
 && rm -rf /var/lib/apt/lists/*

RUN useradd -m -s /bin/bash rails && mkdir -p /workspace && chown -R rails:rails /workspace
WORKDIR /workspace
USER rails

EXPOSE 3000

Dockerfile 解説(開発環境)

ベースイメージの指定
FROM ruby:3.4.7-bookworm

公式のRubyイメージを使用。bookwormはDebian 12のコードネーム。

環境変数の設定
ENV DEBIAN_FRONTEND=noninteractive \
    RAILS_ENV=development \
    TZ=Asia/Tokyo \
    LANG=C.UTF-8 \
    LC_ALL=C.UTF-8
  • RAILS_ENV=development: 開発モードで起動
  • TZ=Asia/Tokyo: タイムゾーンを日本時間に設定
  • LANG=C.UTF-8: 文字化け防止
必要なパッケージのインストール
RUN apt-get update && apt-get install -y --no-install-recommends \
    bash git curl tzdata ca-certificates tree \
    build-essential pkg-config libpq-dev \
    nodejs postgresql-client \
 && rm -rf /var/lib/apt/lists/*
  • libpq-dev: PostgreSQL接続用ヘッダファイル(pggemのビルドに必要)
  • postgresql-client: psqlコマンド用
  • build-essential: ネイティブ拡張のgemをビルドするため
  • rm -rf /var/lib/apt/lists/*: イメージサイズ削減
非rootユーザーの作成
RUN useradd -m -s /bin/bash rails && mkdir -p /workspace && chown -R rails:rails /workspace
WORKDIR /workspace
USER rails

セキュリティのため、rootではなくrailsユーザーで実行。

docker-compose.yml(開発用)

.devcontainer/backend/docker-compose.yml:

version: "3.9"

services:
  app:
    build:
      context: ../..  # プロジェクトルートをビルドコンテキストに指定
      dockerfile: .devcontainer/backend/Dockerfile
    volumes:
      - ../..:/workspace  # ローカルのプロジェクト全体をマウント
    working_dir: /workspace/backend
    ports:
      - "3000:3000"
    environment:
      RAILS_ENV: development
      POSTGRES_HOST: db
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    depends_on:
      - db
    command: sleep infinity
    tty: true

  db:
    image: postgres:16
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    ports:
      - "5432:5432"
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

docker-compose.yml 解説(開発環境)

appサービス
  • build.context: プロジェクトルート(../..)をビルドコンテキストに
  • volumes: ホストのコードをコンテナにマウント(リアルタイム反映)
  • command: sleep infinity: コンテナを起動したまま維持
  • depends_on: PostgreSQLコンテナが先に起動
dbサービス
  • image: postgres:16: 公式PostgreSQL 16を使用
  • volumes: db-data: データ永続化(コンテナ削除後もデータ保持)

devcontainer.json

.devcontainer/backend/devcontainer.json:

{
  "name": "Backend Dev Container",

  "dockerComposeFile": "docker-compose.yml",
  "service": "app",

  "workspaceFolder": "/workspace",

  "remoteUser": "rails",
  "updateRemoteUserUID": true,
  "overrideCommand": false,

  "postCreateCommand": "bash -lc 'gem install bundler -N && gem install rails -N -v \"~> 7.2\" && bundle install'"
}

devcontainer.json 解説

項目 説明
dockerComposeFile 使用するdocker-compose.ymlを指定
service VSCodeが接続するサービス名(app
workspaceFolder コンテナ内の作業ディレクトリ
remoteUser コンテナ内でのユーザー(rails
postCreateCommand コンテナ作成後に自動実行(bundler、Railsのインストール)

環境変数ファイル

.devcontainer/backend/.env:

POSTGRES_USER=app
POSTGRES_PASSWORD=password
POSTGRES_DB=backend_development

注意: .envファイルは.gitignoreに追加し、Git管理しないこと。


本番環境の構築

Dockerfile(本番用)

backend/docker/Dockerfile:

FROM ruby:3.4.7-bookworm

ENV DEBIAN_FRONTEND=noninteractive \
    RAILS_ENV=production \
    TZ=Asia/Tokyo \
    LANG=C.UTF-8 \
    LC_ALL=C.UTF-8

# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y --no-install-recommends \
    bash git curl tzdata ca-certificates \
    build-essential pkg-config libpq-dev \
    nodejs postgresql-client \
 && rm -rf /var/lib/apt/lists/*

# アプリケーションディレクトリ
WORKDIR /app

# Gemfileをコピーして依存関係をインストール
COPY Gemfile Gemfile.lock ./
RUN bundle config set --local deployment 'true' && \
    bundle config set --local without 'development test' && \
    bundle install

# アプリケーションコードをコピー
COPY . .

# アセットのプリコンパイル(エラー回避用)
RUN bundle exec rails assets:precompile || true

EXPOSE 3000

CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]

Dockerfile 解説(本番環境)

開発環境との違い
  1. RAILS_ENV=production: 本番モード
  2. bundle config set --local deployment 'true': Gemfile.lockを厳密に遵守
  3. bundle config set --local without 'development test': 開発・テスト用gemを除外
  4. COPY . .: コードをコンテナ内にコピー(ボリュームマウントしない)
  5. CMD: Railsサーバーを自動起動

docker-compose.yml(本番用)

AWSのS3からデータをインポートしたりしていたので、その分の設定が追加されています

backend/docker/docker-compose.yml:

version: "3.9"

services:
  app:
    build:
      context: ..
      dockerfile: docker/Dockerfile
    env_file:
      - .env
    ports:
      - "3000:3000"
    environment:
      RAILS_ENV: production
      POSTGRES_HOST: db
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      AWS_REGION: ${AWS_REGION}
      AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
      AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
      S3_BUCKET_NAME: ${S3_BUCKET_NAME}
      SECRET_KEY_BASE: ${SECRET_KEY_BASE}
    depends_on:
      - db
    command: bundle exec rails server -b 0.0.0.0
    restart: unless-stopped

  db:
    image: postgres:16
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - db-data:/var/lib/postgresql/data
    restart: unless-stopped

volumes:
  db-data:

docker-compose.yml 解説(本番環境)

開発環境との違い
  1. env_file: - .env: 環境変数ファイルを読み込み
  2. AWS関連の環境変数: S3連携のため
  3. SECRET_KEY_BASE: Rails本番環境で必須
  4. restart: unless-stopped: コンテナが落ちたら自動再起動
  5. ボリュームマウントなし: コードはコンテナ内に固定

開発環境と本番環境の違い

項目 開発環境 本番環境
ベースイメージ ruby:3.4.7-bookworm ruby:3.4.7-bookworm
RAILS_ENV development production
依存関係 development/test含む productionのみ
コード配置 ホストをボリュームマウント COPYでコンテナ内に固定
bundle deployment false true(Gemfile.lock厳守)
環境変数 .devcontainer/backend/.env backend/docker/.env
自動起動 なし(sleep infinity) Railsサーバー自動起動
再起動ポリシー なし unless-stopped
ユーザー rails(非root) root

使用方法

開発環境の起動

  1. VSCodeでプロジェクトルートを開く
  2. Cmd/Ctrl + Shift + PDev Containers: Reopen in Container
  3. Backend Dev Containerを選択
  4. 初回はビルドに数分かかる
  5. コンテナ内のターミナルが開く

データベース準備

# マイグレーション実行
rails db:create
rails db:migrate

# 開発サーバー起動
rails server

ブラウザで http://localhost:3000 にアクセス

本番環境の起動

cd backend/docker

# .envファイルを作成(.env.exampleを参考に)
cp .env.example .env
vim .env

# コンテナビルド・起動
docker-compose up -d --build

# データベース作成
docker-compose exec app bundle exec rails db:create
docker-compose exec app bundle exec rails db:migrate

おわりに

Devcontainer + Docker Composeを使うことで、環境構築の手間を大幅に削減し、チーム開発をスムーズに進められます。

開発環境と本番環境の設定を分離しつつ、Dockerfileを共通化することで、「ローカルでは動くのに本番で動かない」という問題を防げます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?