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?

DevContainerでNestJS + Oracle XE学習環境を構築する

Posted at

NestJS + BFFパターンを学習するため、DevContainerで開発環境を構築しました。

学習としてBFF(Backend for Frontend)パターンを実践的に学ぶプロジェクトを立ち上げました。企画・設計はClaude Desktopとの対話で作り上げ、いざ環境構築に着手したところ、いくつかの問題に遭遇しました。

特にOracle Container Registryの認証方式が変更されていた点で解決に時間を要したため、技術記録として残しておきます。

リポジトリ: https://github.com/d-kishi/nestjs-bff-learning
企画成果物: project-plan.md
→この企画成果物をベースに、ClaudeCodeで以下のようなプロンプトで環境構築を始めました。

@docs/project-plan.md を読んで、このプロジェクトの初期セットアップを行ってください。

実施してほしいこと:
1. README.md の作成(企画書の要約版)
2. /init を実行してCLAUDE.mdを生成
3. 生成されたCLAUDE.mdを企画書の内容に基づいて調整
4. 基本的なディレクトリ構造の作成
5. ルートのpackage.json(npm workspaces設定)の作成

企画書には技術スタック、アーキテクチャ、開発規約、ADR(設計判断記録)がすべて含まれています。

技術スタック

学習プロジェクトで採用した主な技術は以下の通りです。

カテゴリ 技術 選定理由
バックエンド NestJS TypeScript対応、モジュラー設計、学習目的に最適
データベース Oracle XE 21c 業務で使用するDBの学習
開発環境 DevContainer 環境構築の再現性、VS Code統合
コンテナ Docker Desktop DevContainerとの統合がシームレス

Docker Desktop vs WSL + Docker Engine

最近はWSL2にDocker Engineを直接インストールし、Docker Desktopを使用しない構成も増えています。今回はDocker Desktopを採用しました。

選定理由:

  • 個人学習プロジェクトのためライセンス費用は発生しない
  • GUIによる管理が容易で、Docker自体の設定に時間をかけずNestJS学習に集中できる
  • VS Code Dev Containers拡張との統合がシームレス
  • 主目的はNestJS/BFF学習であり、Linux環境の深い理解は副次的

企業利用の場合はライセンス費用が発生する可能性があるため、WSL2 + Docker Engine構成も検討の価値があります。

アーキテクチャ概要

学習プロジェクトでは、BFF(Backend for Frontend)パターンを採用したマイクロサービス構成を目指しています。

サービス ポート 役割
api-gateway 3000 BFF層。JWT検証、サービス集約、部分失敗ハンドリング
task-service 3001 タスク管理(Project, Task, Comment, Tag)
user-service 3002 ユーザー管理・認証(User, UserProfile, Role)、JWT発行
Oracle XE 1521 データベース

BFF層(api-gateway)がフロントエンドからのリクエストを受け、必要に応じて複数のバックエンドサービスからデータを集約して返却します。

DevContainer環境構築

コンテナ構成

コンテナ 役割 イメージ
app Node.js + Oracle Instant Client カスタムビルド
oracle Oracle Database XE 21c container-registry.oracle.com/database/express:21.3.0-xe

devcontainer.json

{
  "name": "NestJS BFF Learning",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace",
  "postCreateCommand": "npm install",
  "forwardPorts": [3000, 3001, 3002, 1521],
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "Orta.vscode-jest",
        "ashinzekene.nestjs",
        "imgildev.vscode-nestjs-snippets-extension",
        "humao.rest-client",
        "christian-kohler.npm-intellisense",
        "christian-kohler.path-intellisense",
        "yoavbls.pretty-ts-errors"
      ],
      "settings": {
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      }
    }
  }
}

ポイント:

  • forwardPorts: 上記アーキテクチャ図の各サービスポート(api-gateway:3000、task-service:3001、user-service:3002)とOracle XE(1521)をホストに転送
  • postCreateCommand: コンテナ作成後に自動でnpm install

docker-compose.yml

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ..:/workspace:cached
    command: sleep infinity
    environment:
      - ORACLE_HOST=oracle
      - ORACLE_PORT=1521
      - ORACLE_SERVICE=XEPDB1
    depends_on:
      oracle:
        condition: service_healthy

  oracle:
    image: container-registry.oracle.com/database/express:21.3.0-xe
    environment:
      - ORACLE_PWD=password
      - ORACLE_CHARACTERSET=AL32UTF8
    ports:
      - "1521:1521"
    volumes:
      - oracle-data:/opt/oracle/oradata
      - ../database/init:/opt/oracle/scripts/startup
    healthcheck:
      test: ["CMD-SHELL", "echo 'SELECT 1 FROM DUAL;' | sqlplus -s system/password@localhost:1521/XEPDB1 || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 10
      start_period: 120s

volumes:
  oracle-data:

ポイント:

  • depends_on.condition: service_healthy: Oracleのヘルスチェック完了を待機
  • start_period: 120s: Oracle初回起動に時間がかかるため余裕を持たせる
  • ../database/init: 初期化SQLスクリプトをマウント

Dockerfile

FROM mcr.microsoft.com/devcontainers/javascript-node:20

# Oracle Instant Client installation
# Note: libaio1 -> libaio1t64 in Debian Trixie
RUN apt-get update && apt-get install -y libaio1t64 wget unzip \
    && wget https://download.oracle.com/otn_software/linux/instantclient/2340000/instantclient-basiclite-linux.x64-23.4.0.24.05.zip \
    && unzip instantclient-basiclite-linux.x64-23.4.0.24.05.zip -d /opt/oracle \
    && rm instantclient-basiclite-linux.x64-23.4.0.24.05.zip \
    && echo /opt/oracle/instantclient_23_4 > /etc/ld.so.conf.d/oracle-instantclient.conf \
    && ldconfig \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

# Set Oracle environment variables
ENV LD_LIBRARY_PATH=/opt/oracle/instantclient_23_4:$LD_LIBRARY_PATH
ENV PATH=/opt/oracle/instantclient_23_4:$PATH

# Install NestJS CLI globally
RUN npm install -g @nestjs/cli

ポイント:

  • libaio1t64: Debian Trixieでのパッケージ名(後述の「問題2」参照)
  • Oracle Instant Client 23.4: node-oracledbとの互換性を確保

構築時の問題と解決策

問題1: Oracle Container Registry認証エラー

現象

docker login container-registry.oracle.com
# Username: メールアドレス
# Password: Oracleアカウントのパスワード
# → Error response from daemon: unauthorized: Auth failed.

通常のOracleアカウントパスワードでは認証に失敗します。

原因

Oracle Container Registryでは、通常のパスワードではなくAuth Token(シークレットキー) が必要です。
2025年6月30日以降、Auth Token認証が必須となり、従来のOracleアカウントパスワードでの認証はできなくなりました。

解決手順

  1. Oracle Container Registryにブラウザでログイン

  2. Auth Tokenを生成

    • 右上のプロフィール名(アカウント名) をクリック
    • メニューから「Auth Token」を選択
    • Generate Secret Key」をクリック
    • 生成されたシークレットキーをコピー(この画面を閉じると再表示不可
  3. docker loginでAuth Tokenを使用

    docker login container-registry.oracle.com
    # Username: Oracleアカウントのメールアドレス
    # Password: 生成したシークレットキー(Auth Token)
    
  4. イメージをpull

    docker pull container-registry.oracle.com/database/express:21.3.0-xe
    

シークレットキーは一度しか表示されないため、安全な場所に保管してください。
また、ライセンス同意はリポジトリ詳細ページで事前に完了しておく必要があります。

問題2: Debian Trixieでlibaio1が見つからない

現象

Dockerfileのビルド中に以下のエラーが発生。

E: Unable to locate package libaio1

原因

Debian Trixie(testing)では、libaio1パッケージがlibaio1t64にリネームされています。
これはDebian/Ubuntuの64ビット移行(time_t 64-bit transition)に伴う変更です。

解決策

Dockerfileでlibaio1libaio1t64に変更します。

# Before
RUN apt-get install -y libaio1 ...

# After
RUN apt-get install -y libaio1t64 ...

この問題はDebian Trixie(testing)ベースのイメージで発生します。
mcr.microsoft.com/devcontainers/javascript-node:20はDebian Trixieベースです。
将来的にDebian安定版でも同様の変更が適用される可能性があります。

問題3: Oracle XE起動に時間がかかる

現象

DevContainer起動後、Oracle XEへの接続が失敗する。

原因

Oracle XEの初回起動には2-3分程度かかります。
コンテナが起動していても、データベースサービスが準備完了していません。

解決策

docker-compose.ymlでヘルスチェックを設定し、依存関係にcondition: service_healthyを指定します。

oracle:
  healthcheck:
    test: ["CMD-SHELL", "echo 'SELECT 1 FROM DUAL;' | sqlplus -s system/password@localhost:1521/XEPDB1 || exit 1"]
    interval: 30s
    timeout: 10s
    retries: 10
    start_period: 120s

app:
  depends_on:
    oracle:
      condition: service_healthy
  • start_period: 120s: 初回起動の猶予期間
  • retries: 10: 最大10回リトライ
  • appコンテナはOracleがhealthyになるまで待機

まとめ

DevContainerでNestJS + Oracle XEの学習環境を構築しました。

特にOracle Container Registryの認証方式変更(Auth Token必須化)は、ドキュメントを見落としがちなポイントです。同様の環境を構築する方の参考になれば幸いです。

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?