Docker 環境で MongoDB を使用する：Dockerfile

# Docker 環境で MongoDB を使用する：Dockerfile

こんにちは、@studio_meowtoon です。今回は、WSL の Ubuntu 24.04 の Docker 環境で MongoDB を使用する手順を紹介します。
![mongodb_on_docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/b648671d-78a0-79df-3db9-8a1f4304055f.png)

## 目的

Windows 11 の Linux でクラウド開発します。

こちらから記事の一覧がご覧いただけます。

https://qiita.com/studio_meowtoon/items/6119ab05d8b13527efd8

## 実現すること

ローカル環境の Ubuntu の Docker 環境で、MongoDB コンテナーを起動します。

**MongoDB をコンテナーとして起動**
```mermaid
flowchart LR
    terminal --> app[mongodb]
    subgraph Ubuntu
        subgraph Docker
            subgraph container[mongodb-todo]
                subgraph mongodb
                    app[db_todo]
                end
            end
        end
    end
style Ubuntu fill:#FFBCA4, stroke:#E0460F
style Docker fill:#EEFDFF, stroke:#74B9DC
style container fill:#FFD7E4, stroke:#E13C73
style mongodb fill:#FFFFDE, stroke:#B4AE43
style app fill:#ECECFF, stroke:#9674DC
```

**実行環境**

|要素|概要|
|:--|:--|
|terminal|ターミナル|
|Ubuntu|OS|
|Docker|コンテナー実行環境|

**データベース コンテナー**

|要素|概要|
|:--|:--|
|mongodb-todo|データベースコンテナー|
|mongodb|DB サーバー|
|db_todo|データベース|

## 技術トピック

### MongoDB とは？  

<details>
<summary>こちらを展開してご覧いただけます。</summary>

### [MongoDB (モンゴディービー)](https://www.mongodb.com/ja-jp)

:::note info
MongoDB は、は、オープンソースのドキュメント指向 NoSQL データベースです。

|キーワード|内容|
|:--|:--|
|ドキュメント指向|データを BSON 形式 (Binary JSON の略) のドキュメントとして保存します。この柔軟なデータモデルは、複雑な階層構造を持つデータや可変スキーマに適しています。|
|スケーラビリティ|水平方向にスケーリングすることで大量のデータを処理できます。クラスタリングやレプリケーションを活用して高可用性も実現できます。|
|高速性|インメモリ処理やディスクへの効率的な書き込みなど、高速なデータ操作が可能です。また、クエリの最適化やインデックスを活用してクエリ速度を向上させることができます。|
|柔軟なスキーマ|データベース内の各ドキュメントは異なるスキーマを持つことができます。これにより、アプリケーションの要件変更に対応しやすく、開発の柔軟性を提供します。|
|JSON ライクなクエリ言語|MongoDB のクエリ言語は JSON に似ており、複雑な条件や集計も直感的に記述できます。さらに、アグリゲーションパイプラインを使用して高度な集計を行うことができます。|
|ユーザー認証とアクセス制御|MongoDB はアプリケーションのセキュリティをサポートし、ユーザーごとにアクセス権限を設定できます。|
|多様なデータタイプのサポート|テキスト、数値、日付、配列、埋め込みドキュメントなど、多様なデータタイプをサポートします。|
|コミュニティとエコシステム|MongoDB は活発なコミュニティと豊富なエコシステムを持ち、多くのドライバーやツールが提供されています。|

:::

</details>

## 開発環境

+ Windows 11 Home 23H2 を使用しています。  

:::note info
[WSL](https://learn.microsoft.com/ja-jp/windows/wsl/about) の Ubuntu を操作しますので macOS の方も参考にして頂けます。  
:::

<details>

WSL (Microsoft Store アプリ版) [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/cd0c4a607d451dbf5430)

```sh
> wsl --version
WSL バージョン: 2.2.4.0
カーネル バージョン: 5.15.153.1-2
WSLg バージョン: 1.0.61
```

Ubuntu [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/cd0c4a607d451dbf5430)

```sh
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04 LTS
Release:        24.04
Codename:       noble
```

Docker [※ こちらの関連記事からインストール方法をご確認いただけます](https://qiita.com/studio_meowtoon/items/3bceee25ac67cc73ebbe)

```sh
$ docker --version
Docker version 27.0.3, build 7d4bcd8
```

</details>

:::note warn
この記事では基本的に **Ubuntu のターミナルで操作**を行います。**Vim を使用してコピペする方法**をはじめて学ぶ人のために、以下の記事で手順を紹介しています。ぜひ挑戦してみてください。
:::

https://qiita.com/studio_meowtoon/items/7771ad48676926e41463

## Docker 環境で MongoDB を使用する手順

### Docker ネットワークを作成します

```sh
$ docker network create net-todo
```

<details>
<summary>説明を開きます。</summary>

|要素|説明|
|:--|:--|
|docker network create|Docker 内でコンテナー間通信を可能にするためのネットワークを作成するコマンドです。|
|net-todo|net-todo という名前の Docker ネットワークが作成されます。|

</details>

:::note warn
今後、このデータベースコンテナーとの間でコンテナー間通信を行うために、**ユーザ定義ネットワーク**を作成しています。
:::

プロジェクトフォルダーを作成して移動します。

```cs
$ mkdir -p ~/tmp/mongodb-base
$ cd ~/tmp/mongodb-base
```

### 初期データの作成

:::note warn
今後、ToDo リストアプリを作成する為に、以下の仕様の初期データを作成します。
:::

**ToDo リストコレクション**
```mermaid
erDiagram
todos {
    TEXT content "内容"
    TIMESTAMP created_date "作成日時"
    TIMESTAMP completed_date "完了日時"
}
```

js ファイルを作成します。

```sh
$ vim init_db.js
```

ファイルの内容

```js:init_db.js
db = db.getSiblingDB('db_todo');

db.todos.insertMany([
    {
        content: '食材を買う',
        created_date: new Date(),
        completed_date: new Date()
    },
    {
        content: '報告書を仕上げる',
        created_date: new Date(),
        completed_date: new Date()
    },
    {
        content: '運動する',
        created_date: new Date(),
        completed_date: new Date()
    },
    {
        content: '本を読む',
        created_date: new Date(),
        completed_date: null
    },
    {
        content: '請求書を支払う',
        created_date: new Date(),
        completed_date: null
    },
    {
        content: '家を掃除する',
        created_date: new Date(),
        completed_date: null
    },
    {
        content: 'プレゼンの準備する',
        created_date: new Date(),
        completed_date: null
    },
    {
        content: 'コードを書く',
        created_date: new Date(),
        completed_date: null
    }
]);
```

Dockerfile を作成します。

```sh
$ vim Dockerfile
```

ファイルの内容

```Dockerfile:Dockerfile
# set up the container.
FROM mongo:7.0-jammy

# set utf-8 encoding and the root user's password.
ENV LANG=ja_JP.UTF-8
ENV MONGO_INITDB_ROOT_USERNAME=root
ENV MONGO_INITDB_ROOT_PASSWORD=password

# copy the init js file to the init dir.
COPY init_db.js /docker-entrypoint-initdb.d/

# expose the port.
EXPOSE 27017
```

<details>
<summary>説明を開きます。</summary>

|要素|説明|
|:--|:--|
|FROM mongo:7.0-jammy|MongoDB の公式ベースイメージ 7.0-jammy を使用しています。|
|ENV LANG=ja_JP.UTF-8|コンテナー内で使用する言語環境を ja_JP.UTF-8 に設定しています。これにより、コンテナー内のテキストエンコーディングが UTF-8 で設定されます。|
|ENV MONGO_INITDB_ROOT_USERNAME=root|MongoDB の初期データベースのルートユーザーのユーザー名を root に設定しています。|
|ENV MONGO_INITDB_ROOT_PASSWORD=password|ルートユーザーのパスワードを password に設定しています。この情報は初期データベースのセットアップ時に使用されます。|
|COPY init_db.js /docker-entrypoint-initdb.d/|init_db.js というファイルをコンテナー内の /docker-entrypoint-initdb.d/ ディレクトリにコピーしています。MongoDB コンテナーはこのディレクトリ内のスクリプトを初期化時に実行します。このスクリプトは、初期データベースやコレクションの作成、データの挿入などを行うために使用されます。|
|EXPOSE 27017|コンテナー内の MongoDB のデフォルトポートである 27017 を外部に公開します。|

</details>

<details>
<summary>vim をインストールする ver はこちら。</summary>

```Dockerfile:Dockerfile
# set up the container.
FROM mongo:7.0-jammy

# install vim.
RUN apt-get update && \
    apt-get install -y vim && \
    rm -rf /var/lib/apt/lists/* && \
    apt-get clean

# add encoding setting to .vimrc file.
RUN echo ':set encoding=utf-8' >> /root/.vimrc

# set utf-8 encoding and the root user's password.
ENV LANG=ja_JP.UTF-8
ENV MONGO_INITDB_ROOT_USERNAME=root
ENV MONGO_INITDB_ROOT_PASSWORD=password

# copy the init js file to the init dir.
COPY init_db.js /docker-entrypoint-initdb.d/

# expose the port.
EXPOSE 27017
```

|要素|説明|
|:--|:--|
|RUN apt-get update|apt-get update は、利用可能なパッケージの最新の情報を取得します。|
|apt-get install -y vim|Vim エディターをインストールしています。-y フラグは、すべてのプロンプトを自動的に Yes で回答することを意味します。|
|rm -rf /var/lib/apt/lists/*|APT のキャッシュや一時ファイルを削除して、イメージサイズを小さくするための一般的なベストプラクティスです。|
|apt-get clean|不要なパッケージファイルをクリーンアップします。これにより、ディスクスペースを節約できます。|
|RUN echo ':set encoding=utf-8' >> /root/.vimrc|Vim の設定ファイルである .vimrc にエンコーディングの設定を追加しています。|

</details>

コンテナーイメージをビルドします。

```sh
$ docker build \
    --no-cache \
    --tag mongo-base:latest .
```

コンテナーイメージを確認します。

```sh
$ docker images | grep mongo-base
mongo-base    latest    bcf6e894a153   9 seconds ago   796MB
```

コンテナーを作成・起動します。

```sh
$ docker run -d \
   --publish 27017:27017 \
   --name mongodb-todo \
   --net net-todo \
   --volume db_todo_mongo:/data/db \
   mongo-base
```

<details>
<summary>説明を開きます。</summary>

|要素|説明|
|:--|:--|
|docker run|新しいコンテナーを作成して実行するコマンドです。|
|-d|-d オプションは、コンテナーをバックグラウンドで実行します。|
|--publish 27017:27017|--publish オプションは、ホストとコンテナー間のポートマッピングを行います。ホスト側のポート 27017 をコンテナーのポート 27017 にマッピングしています。|
|--name mongodb-todo|--name オプションは、コンテナーに mongodb-todo という名前を付けます。これにより、あとでコンテナーを識別しやすくなります。|
|--net net-todo|--net オプションは、コンテナーで使用する Docker ネットワークを指定します。|
|--volume db_todo_mongo:/data/db|--volume オプションは、Docker ボリュームを作成し、コンテナー内の /data/db ディレクトリにマウントします。db_todo_mongo という名前のボリュームが作成されます。これにより、データベースのデータが永続化されます。|
|mongo-base|MongoDB のカスタムコンテナーイメージを指定しています。このイメージを基にしてコンテナーが作成され、MongoDB データベースが実行されます。|

</details>

:::note warn
このコンテナーを停止する場合には、以下のコマンドを実行します。

```sh
$ docker stop mongodb-todo
```

次にこのコンテナーを起動する場合には、以下のコマンドを実行します。

```sh
$ docker start mongodb-todo
```

:::

:::note info
ここまでの手順で MongoDB の**コンテナー**を作成し、**データベース**と**コレクション**を作成、また**コレクション**にデータを挿入することができました。
:::

### コンテナー内の MongoDB に接続します

コンテナーに接続します。
※ コンテナーから出るときは ctrl + D を押します。

```sh
$ docker exec -it mongodb-todo /bin/sh
```

<details>
<summary>説明を開きます。</summary>

|要素|説明|
|:--|:--|
|docker exec|実行中のコンテナー内でコマンドを実行するコマンドです。|
|-it mongodb-todo|対話的なシェルセッションを開始するためのフラグです。これにより、mongodb-todo コンテナー内のシェルに対して入出力が可能になります。|
|/bin/sh|コンテナー内で実行するコマンドを指定します。ここではコンテナー内のデフォルトシェルである /bin/sh を起動しています。|

</details>

mongosh のバージョンを確認します。

```cs
# mongosh --version
2.2.10
```

MongoDB に接続します。
※ MongoDB から出るときは ctrl + D を押します。

```cs
# mongosh --host localhost \
    --port 27017 \
    --username root \
    --password password \
    --authenticationDatabase admin
```

バージョンが表示されています。

```sh
Using MongoDB:          7.0.12
Using Mongosh:          2.2.10
```

データベースの一覧を表示します。

```sh
test> show dbs
admin    100.00 KiB
config    12.00 KiB
db_todo   40.00 KiB
local     72.00 KiB
```

db_todo データベースを選択します。

```sh
test> use db_todo
switched to db db_todo
```

コレクションの一覧を表示します。

```sh
test> show collections
todos
```

コレクションのデータを表示します。

```sh
test> db.todos.find()
[
  {
    _id: ObjectId('66b7f3866c2fb3b3a7149f48'),
    content: '食材を買う',
    created_date: ISODate('2024-08-10T23:11:02.524Z'),
    completed_date: ISODate('2024-08-10T23:11:02.524Z')
  },
  {
    _id: ObjectId('66b7f3866c2fb3b3a7149f49'),
    content: '報告書を仕上げる',
    created_date: ISODate('2024-08-10T23:11:02.524Z'),
    completed_date: ISODate('2024-08-10T23:11:02.524Z')
  },
  {
    _id: ObjectId('66b7f3866c2fb3b3a7149f4a'),
    content: '運動する',
    created_date: ISODate('2024-08-10T23:11:02.524Z'),
    completed_date: ISODate('2024-08-10T23:11:02.524Z')
  },
  {
    _id: ObjectId('66b7f3866c2fb3b3a7149f4b'),
    content: '本を読む',
    created_date: ISODate('2024-08-10T23:11:02.524Z'),
    completed_date: null
  },
  {
    _id: ObjectId('66b7f3866c2fb3b3a7149f4c'),
    content: '請求書を支払う',
    created_date: ISODate('2024-08-10T23:11:02.524Z'),
    completed_date: null
  },
  {
    _id: ObjectId('66b7f3866c2fb3b3a7149f4d'),
    content: '家を掃除する',
    created_date: ISODate('2024-08-10T23:11:02.524Z'),
    completed_date: null
  },
  {
    _id: ObjectId('66b7f3866c2fb3b3a7149f4e'),
    content: 'プレゼンの準備する',
    created_date: ISODate('2024-08-10T23:11:02.524Z'),
    completed_date: null
  },
  {
    _id: ObjectId('66b7f3866c2fb3b3a7149f4f'),
    content: 'コードを書く',
    created_date: ISODate('2024-08-10T23:11:02.524Z'),
    completed_date: null
  }
]
```

:::note info
ここまでの手順で MongoDB に接続し、**データベース**と**コレクション**の内容を確認することができました。
:::

## GUI クライアントから確認

https://www.mongodb.com/ja-jp/products/compass

MongoDB を GUI から操作する統合ビジュアルツールとして MongoDB Compass があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206449/dccd157d-34c7-8709-93ce-b00c9e01d174.png)

## まとめ

ローカル環境の Ubuntu の Docker 環境で、MongoDB コンテナーを起動することができました。

:::note warn
クラウド開発においては、**Dockerfile の理解**は重要です。自動ビルドツールもありますが、手動で書く必要があるケースもあります。**Ubuntu** を使うと **Linux の知識**も身に付きます。最初は難しく感じるかもしれませんが、徐々に進めていけば自信を持って書けるようになります。
:::

どうでしたか？　MongoDB の操作には、この他にもたくさんのコマンドがあります。みなさんも少しづつ試してみてください。今後も開発環境などを紹介しますので、ぜひお楽しみにしてください。

## 推奨コンテンツ

https://qiita.com/studio_meowtoon/items/f02b64bce0ce276fd57f