前回の記事「DockerとExpress.jsを用いたアプリをElastic Beanstalkにデプロイする手順」では、Express.jsを使用してシンプルなWebアプリケーションを開発し、それをDockerでコンテナ化する手順を解説した。
今回は、ExpressアプリとMongoDBを接続し、データの登録から取得までを行う手順をまとめる。尚、当該手順はローカル環境での検証を前提としたものである。
環境
パッケージ
"express": "^4.19.2"
"mongoose": "^8.3.2"Dockerバージョン: 4.26.1
Dockerの設定
docker-compose.ymlの作成
Docker Compose を使用して、Express と MongoDB のコンテナを同時に起動できるようにする。
# docker-compose記法のバージョン
version: "3.8"
# 起動するコンテナの種類を定義
services:
  # Express.jsアプリケーションレイヤーの設定
  app-name:
    build: .
    ports:
      - "3000:3000"
    environment:
      - MONGO_URI=mongodb://mongo:27017/xxxxxxDB
    depends_on:
      - mongo
    volumes:
      - .:/usr/src/app
      - /usr/src/app/node_modules
  # mongoDBのコンテナ設定
  mongo:
    image: mongo
    ports:
      - "27017:27017"
    volumes:
      - mongodata:/data/db
volumes:
  mongodata:
・サービス名(app-name)の箇所は、プロジェクト名がわかるように任意の名称を設定
・環境変数: MongoDBの接続URIを MONGO_URI 環境変数として設定。これは dist/index.js 内で使用されることを想定。
Express アプリケーションの設定
必要なパッケージのインストール
まず、mongooseとTypeScriptの型定義ファイルをインストールする。
$ npm i mongoose
$ npm i @types/mongoose --save-devTypeScript で MongoDB 接続モジュールを設定
src/db.tsを作成し、以下の実装を行う。
import mongoose from "mongoose";
const mongoURI: string =
  process.env.MONGO_URI || "mongodb://localhost:27017/xxxxxxDB";
// データベースへの接続
export const connectDB = async (): Promise<void> => {
  try {
    await mongoose.connect(mongoURI);
    console.log("MongoDB connected successfully");
  } catch (error) {
    console.error("MongoDB connection error:", error);
    // 失敗した場合はアプリケーションを終了
    process.exit(1);
  }
};
// データベースとの接続解除
export const disconnectDB = async () => {
  try {
    await mongoose.disconnect();
  } catch (error) {
    console.error("MongoDB disconnect error:", error);
    // 失敗した場合はアプリケーションを終了
    process.exit(1);
  }
};
アプリケーションでMongoDB 接続モジュールを使用する。
Expressアプリケーションのメインファイル(src/index.ts)で、この接続モジュールをインポートし、アプリケーション起動時にデータベースに接続する。
import express, { Application, Request, Response } from "express";
import { connectDB } from "./db"; // 接続モジュールをインポート
const app: Application = express();
app.use(express.json());
const port = process.env.PORT || 3000;
// DB接続
connectDB();
app.get("/", (req: Request, res: Response) => {
  res.send("Hello Docker!");
});
app.listen(port, () => {
  console.log(`App listening on port ${port}`);
});
接続確認
`npm run build` を実行し、以下のコマンドでDockerコンテナを起動する。
$ docker-compose up --build「MongoDB connected successfully」「App listening on port 3000」のログが出力できれば接続に成功している。
ダミーデータの登録
DBとの接続に成功したので、実際にデータを登録してみる。
今回は「職種」データを表現するJobTypeモデルを作成し、/api/master/job-typesにアクセスした際に、登録した職種の一覧が表示されるようにする。
MongoDB スキーマの設定
Mongooseを使用して、JobType スキーマを定義する。src/models/JobType.tsを作成する。
import mongoose from "mongoose";
export interface IjobType extends Document {
  name: string;
  memo?: string;
}
const jobTypeSchema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: true,
    },
    memo: {
      type: String,
    },
  },
  {
    timestamps: true,
  }
);
const JobType = mongoose.model<IjobType>("JobType", jobTypeSchema);
export default JobType;
ダミーデータの挿入
src/test/models/insertData.tsを作成し、以下のコードを記述。
このファイルはnodeコマンドで個別に適用する。
import JobType from "../../models/JobType";
import { connectDB, disconnectDB } from "../../db";
// DB接続
connectDB();
async function insertDummyJobTypes() {
  const jobTypes = [
    { name: "Software Developer", memo: "Develops applications." },
    { name: "Data Scientist", memo: "Analyzes complex data." },
    { name: "Product Manager", memo: "Manages product lifecycle." },
  ];
  try {
    // 既存のデータをクリア
    await JobType.deleteMany({});
    // insert
    await JobType.insertMany(jobTypes);
    console.log("Dummy job types data inserted!");
  } catch (error) {
    console.error("Error inserting data", error);
  } finally {
    disconnectDB();
  }
}
insertDummyJobTypes();
nodeを実行して、データを登録する。
node src/test/models/insertData.tsAPI エンドポイントの作成
src/routes/jobTypes.tsを作成し、JobType データの取得用のルーティングを設定する。
import express from "express";
import JobType from "../models/JobType";
const router = express.Router();
router.get("/master/job-types", async (req, res) => {
  try {
    // 一覧を取得
    const jobTypes = await JobType.find();
    res.json(jobTypes);
  } catch (error) {
    res.status(500).json({ message: "error fetch jobTypes" });
  }
});
export default router;
Expressアプリにルーターを組み込む
Expressアプリケーションのメインファイル(src/index.ts)で、ルーターの設定を行う。
import express, { Application, Request, Response } from "express";
import { connectDB } from "./db";
// ルーターをインポート
import jobTypeRouter from "./routes/jobTypes";
const app: Application = express();
const port = process.env.PORT || 3000;
// DB接続
connectDB();
app.use(express.json());
// ルーターを実行
app.use("/api", jobTypeRouter);
app.get("/", (req: Request, res: Response) => {
  res.send("Hello Docker!");
});
app.listen(port, () => {
  console.log(`App listening on port ${port}`);
});
以下のコマンドでdockerコンテナを起動する。
$ docker-compose up --buildhttp://localhost:3000/api/master/job-typesにアクセスすると、登録したデータが表示される。
[
{"_id":"662384c04d417182dcb2f75f","name":"Software Developer","memo":"Develops applications.","__v":0,"createdAt":"2024-04-20T09:02:56.023Z","updatedAt":"2024-04-20T09:02:56.023Z"},
{"_id":"662384c04d417182dcb2f760","name":"Data Scientist","memo":"Analyzes complex data.","__v":0,"createdAt":"2024-04-20T09:02:56.024Z","updatedAt":"2024-04-20T09:02:56.024Z"},
{"_id":"662384c04d417182dcb2f761","name":"Product Manager","memo":"Manages product lifecycle.","__v":0,"createdAt":"2024-04-20T09:02:56.024Z","updatedAt":"2024-04-20T09:02:56.024Z"}
] 
         
        




コメント