Dev ContainersでMongoDB＋Mongo-express環境を構築する

構築時に躓いたので、技術メモとして残しておきます。

# やりたかったこと
開発用のAPサーバ、DBサーバをDev Containerから建てたかった。
- APサーバ: python
- DBサーバ: Mongo DB
- DB UIツール: Mongo-Express

# 参考にした記事
https://qiita.com/ryuseiyarou/items/5849bb8cb8d0ffeaba57
https://zenn.dev/koshilife/articles/549555997e9e16
https://hub.docker.com/_/mongo

# ホストOS
debian 12

# 前提条件
以下インストール済みであること
* Visual Studio Code(以下vscode)
* Docker (Docker Compose, Docker Desktop)
* Dev Containers(vscode拡張 Identifier: ms-vscode-remote.remote-containers)

# ディレクトリ構成
        .
        ├── .devcontainer
        |        ├── database
        |        |      ├── Dockerfile // DBサーバ構築用のDockerfile 
        |        |      └── init.js // DB初期データ投入用のScript
        |        ├── Dockerfile // APPサーバ構築用のDockerfile 
        |        ├── dev-requirements.txt // 開発環境のみで使うパッケージ群(Linter等)
        |        ├── devcontainer.json
        |        └── docker-compose.yml
        └── src
             └── requirements.txt // 本番環境でもインストールするパッケージ群
    
# 手順
1. .devcontainer/devcontainer.jsonを作成
    ```json:.devcontainer/devcontainer.json
    {
        "name": "任意の名前",
        "dockerComposeFile": [
            "docker-compose.yml"
        ],
        "service": "app",
        "workspaceFolder": "/workspace",
        "initializeCommand": "ls", // 詳しくはこちらを参照(https://github.com/microsoft/vscode-remote-release/issues/9302)
        "features": {
            "ghcr.io/devcontainers/features/github-cli:1": {},
            "ghcr.io/devcontainers-contrib/features/mongodb-atlas-cli-homebrew:1": {}
        },
        "customizations": {
            "vscode": {
                // devcontainer環境に入れたいvscode拡張、設定を入れる
                "extensions": [
                    "mhutchie.git-graph",
                    "donjayamanne.githistory",
                    "eamodio.gitlens",
                    "Gruntfuggly.todo-tree",
                    "PKief.material-icon-theme",
                    "mongodb.mongodb-vscode",
                    "ms-python.python",
                    "ms-python.mypy-type-checker",
                    "ms-python.black-formatter",
                    "ms-python.flake8",
                    "ms-python.isort"
                ],
                "settings": {
                    "editor.defaultFormatter": "ms-python.black-formatter",
                    "editor.formatOnSave": true,
                    "editor.tabSize": 2,
                },
            }
        },
        // Use 'postCreateCommand' to run commands after the container is created.
        "postCreateCommand": "pip install --no-cache-dir -r ./src/requirements.txt -r ./.devcontainer/dev-requirements.txt",
        // Use 'forwardPorts' to make a list of ports inside the container available locally.
        "forwardPorts": [
            27017
        ]
    }
    ```
    
1. docker-compose.yml・Dockerfileを作成
    ```yaml:docker-compose.yml
    version: '3.8'
    
    services:
      # APサーバの設定
      app:
        build: 
          context: .
          dockerfile: Dockerfile
        volumes:
          - ../:/workspace
        command: sleep infinity
        network_mode: service:mongo
        
      # DBサーバの設定
      mongo:
        build: 
          context: .
          dockerfile: ./database/Dockerfile
        restart: always
        volumes:
          - ./database:/database
          
      # DB参照GUIツール
      mongo-express:
        image: mongo-express
        restart: always
        # このポート設定を変更するとアクセスできなくなる
        ports:
          - 8081:8081
        environment:
          ME_CONFIG_MONGODB_ADMINUSERNAME: root
          ME_CONFIG_MONGODB_ADMINPASSWORD: example
          ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017
        depends_on:
          - mongo
    ```

    ```Dockerfile:.devcontainer/Dockerfile
    FROM python:3.12-slim
    ```
    ```Dockerfile:.devcontainer/database/Dockerfile
    FROM mongo:latest

    ENV MONGO_INITDB_ROOT_USERNAME="root"
    ENV MONGO_INITDB_ROOT_PASSWORD="example"
    ENV MONGO_INITDB_DATABASE="your_db_name"
    
    ENV TZ="Asia/Tokyo"
    RUN echo $TZ > /etc/timezone
    
    COPY ./database/init.js /docker-entrypoint-initdb.d/
    ```
    ```javascript:.devcontainer/database/init.js
    db.createCollection("your_collection_name")
    db.your_collection_name.insert({something:"data"})
    // insertMany
    ```
1. vscodeからDev Containers起動
    1. F1キーを押す
    1. Dev Containers: Open Folder in Container...を実行
    1. 表示されるウィンドウからOpenでビルド処理が軌道
    1. 特にエラーログが出なければ、構築完了！

1. Mongo-Expressは以下の手順で開く
    1. ブラウザからlocalhost:8081でアクセス
    1. ログイン情報を聞かれるので、以下を入力
        - user: admin
        - password: pass
    1. ログイン完了！
    ![Screenshot from 2024-01-05 12-16-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344302/1f71742c-6f12-0a5a-deb5-b30688ffdeeb.png)
    ※Databasesの部分に初期セットアップで作ったDBが入ります

Dev Containersは一度やり方を確立したら、似たような環境は流用で簡単に開発環境を構築できるので重宝しています。

Python