1
3

More than 1 year has passed since last update.

docker-composeで認証ありmongoDBを立ててPyMongoでアクセスしてみる

Posted at

はじめに

docker-composeでmongoDBを認証ありで立てたときに、PyMongoでどうやってアクセスすれば...となったりしたので、まとめてみました。

本稿では以下順でご紹介していきます。

  1. docker-composeで認証ありmongoDBをつくる
  2. ユーザーを追加する(PyMongo)
  3. 作成したユーザーでmongoDBを制御する(PyMongo)

環境情報は以下となります。

  • Python : 3.8.0
  • PyMongo : 3.12.1
  • MongoDB : 5.0.4

※本稿ではすでにPythonやdockerなどの環境が揃っているものとして進めます。

1.docker-composeで認証ありmongoDBをつくる

MongoDBのdockerコンテナ 「mongo」を作成します。  

使用コード

dokcer-compose.yml

version: '3'
services:
    mongo:
        image: mongo:5.0.4
        container_name: mongo
        ports:
            - 27017:27017
        volumes:
            - ./mongo/db:/data/db
            - ./mongo/configdb:/data/configdb
        environment:
            MONGO_INITDB_ROOT_USERNAME: root     # ここがポイント!
            MONGO_INITDB_ROOT_PASSWORD: root
            TZ: Asia/Tokyo

実行コマンド

上記docker-compose.ymlのある場所で以下コマンドを実行してください。

$docker-compose up --build

説明

□ポイント

ポイントはMONGO_INITDB_ROOT_USERNAMEMONGO_INITDB_ROOT_PASSWORDです。  
ここで指定したユーザー名とパスワードがスーパーユーザーとなります。  

本稿ではスーパーユーザー設定は以下としてます。  

  • ユーザー名 : root
  • パスワード : root

通常mongoDBに認証をつけるには「authorization: enabledを指定」や「--authをつけてmongo実行」などする必要があるみたいですが、docker-composeの場合は上記定義を書けば立ち上げ時点から認証有効になるようです。

2.ユーザーを追加する(PyMongo)

スーパーユーザーを使うことでもアクセスはできますが、セキュリティのためにも今回はアクセス用のユーザーを用意しましょう。

使用コード

add_user.py

from pymongo import MongoClient

host_name = "localhost"
port_num  = 27017
user_name = "py_user"     # 作成ユーザーの名前
user_pwd  = "py_pwd"      # 作成ユーザーのパスワード
db_name   = "sample-db"   # 対象データベース

# スーパーユーザーでアクセス
client = MongoClient(
    host = host_name,
    port = port_num,
    username = "root",      # ここがポイント1個目!
    password = "root",
)

# 「sample-db」データベースにユーザーを追加
db = client[db_name]
db.command(                 # ここがポイント2個目!
  'createUser', 
  user_name,
  pwd=user_pwd,
  roles=['readWrite'],
)

# user確認
for user in db.command('usersInfo').get('users'):
    print(user)

client.close()

実行コマンド

上記Pythonを実行して以下結果が得られれば成功です。

$python add_user.py
{'_id': 'sample-db.py_user', 'userId': UUID('82aee8a5-58a0-4314-979a-48131dd8eec3'), 'user': 'py_user', 'db': 'sample-db', 'roles': [{'role': 'readWrite', 'db': 'sample-db'}], 'mechanisms': ['SCRAM-SHA-1', 'SCRAM-SHA-256']}

※userIdは環境依存です。

説明

□ポイント1個目

手順1にてdokcerコンテナを立てた時点で認証が有効なので、docker-composeで定義したスーパーユーザーでアクセスする必要があります。  
そこでMongoClientにて「username = "root"」「password = "root"」を指定することで、スーパーユーザーとして接続するようにしています。

□ポイント2個目

ユーザーを追加するApiは以下となります。

db = client['<ユーザーを追加する対象DB名>']
db.command(
    'createUser', 
    '<追加したいユーザー名>', 
    pwd='<追加ユーザーのパスワード>',
    roles=['<権限>'],
)

※補足

ユーザー追加方法として以下方法もあります。
しかし、adduserはPyMongo4.0で削除予定とのことで非推奨のようです。

db = client[db_name]
db.adduser(
    '<追加したいユーザー名>', 
    pwd='<追加ユーザーのパスワード>',
    roles=['<権限>']
)

3.作成したユーザーでmongoDBを制御する(PyMongo)

先ほど作成したユーザーで実際に制御してみます。

使用コード

accsess_insert.py

from pymongo import MongoClient

host_name = "localhost"
port_num  = 27017
user_name = "py_user"     # 作成ユーザーの名前
user_pwd  = "py_pwd"      # 作成ユーザーのパスワード
db_name   = "sample-db"   # 対象データベース
co_name   = "sample-co"

# 作成ユーザーでアクセス
client = MongoClient(
    host = host_name,
    port = port_num,
    username = user_name,
    password = user_pwd,
    authSource = db_name,    # ここがポイント!
)

db = client[db_name]
co = db[co_name]

# データを追加
data1 = {
    "name":"TestBook",
    "price":420,
}
co.insert_one(data1)

data2 = {
    "name":"ProgramText",
    "price":1500,
    "category":"IT",
}
co.insert_one(data2)

# 全件表示
for data in co.find():
    print(data)

client.close()

実行コマンド

上記Pythonを実行して以下結果が得られれば成功です。

$python accsess_insert.py
{'_id': ObjectId('619f9fdda0c5b80b201aa550'), 'name': 'TestBook', 'price': 420}
{'_id': ObjectId('619f9fdda0c5b80b201aa551'), 'name': 'ProgramText', 'price': 1500, 'category': 'IT'}

説明

□ポイント

MongoClientの指定にauthSourceを追加しました。

authSourceには認証のために参照するデータベースを指定できます。

今回は「sample-db」を指定することで、手順2で作成したユーザー「py_user」として接続できるようになります。

ちなみに、authSourceを省略した場合は「admin」データベースが参照先となります。  
(例えば手順2のときは省略しているのでadminを参照してます)

※補足

アクセスユーザーを指定する方法として以下方法もあります。
しかし、authenticateは今では非推奨のようです。

client = MongoClient(host_name, port_num)
client[db_name].authenticate(user_name, user_pwd)
co = client[db_name][co_name]

最後に

何も考えずdockerでmongoDBを作ると認証を忘れがちだと思うので、認証をつけるよう気をつけましょう。

余談ですが、バージョンアップに従い非推奨Apiが増えていたので、公式ドキュメントは読まないといけないなと実感しました...(今更ですが)  

参考

PyMongo Documentation

1
3
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
1
3