はじめに
docker-composeでmongoDBを認証ありで立てたときに、PyMongoでどうやってアクセスすれば...となったりしたので、まとめてみました。
本稿では以下順でご紹介していきます。
- docker-composeで認証ありmongoDBをつくる
- ユーザーを追加する(PyMongo)
- 作成したユーザーで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_USERNAME
とMONGO_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が増えていたので、公式ドキュメントは読まないといけないなと実感しました...(今更ですが)