はじめてのMongoDB with Docker
はじめに
MongoDB に入門したので、勉強したことをメモ。
環境作って、基本操作を試すところまで。
レプリカセットとかシャーっディングとか運用っぽい話はスコープ外。
migration もスコープ外。
MongoDB って?
- MongoDB: The Developer Data Platform | MongoDB | MongoDB
- MongoDB Inc. が開発とサポートしてる。
- OSS だけど、少し特殊なライセンス。
- Server Side Public License (SSPL)っていうライセンス(SaaS として提供するときに制限がかかる)
- 機能強化された商用版もある
- 管理ツールとかマネージドサービスとかが、本体と別で提供されてる。
- NoSQL(スキーマレス、基本結合操作しない、スケールアウトしやすい、トランザクション処理しない)
- JSON を使ったドキュメント指向データベース
- JavaScript ライクなクエリ
- DBMS のランキングで 5 位
- NoSQL で 1 位
環境構築
docker compose
mongod が動いてるコンテナとクライアントのコンテナを用意する。
公式と先人の情報を参考に環境を構築した。あっさりできた。
mongo - Official Image | Docker Hub
MongoDB と Mongo-express を docker-compose で立ち上げる | Yukkuri Machine Learning
docker-compose で mongoDB 環境を構築して使う - Qiita
そのままコピペも微妙かなと思って、3 点変更した。
network を設定してみたのと、volume の書き方変えてみたのと、クライアント用に環境変数設定なしで、もう一つ mongo コンテナを立ち上げてみたのと。
version: "3.1"
services:
mongo:
image: mongo
networks:
- mongo_network
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: password
volumes:
- mongodb_data1:/data/db
mongo-express:
image: mongo-express
networks:
- mongo_network
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: password
ME_CONFIG_MONGODB_SERVER: mongo
depends_on:
- mongo
mongo-client:
image: mongo
networks:
- mongo_network
restart: always
volumes:
- mongodb_data2:/data/db
volumes:
mongodb_data1:
mongodb_data2:
networks:
mongo_network:
mongo-express もすんなり繋がった。
docker compose up
するときに、下記ワーニングが出てたけど、ローカルで動かすだけだから一旦無視することにした。
hello-mongo-mongo-express-1 | Server is open to allow connections from anyone (0.0.0.0)
hello-mongo-mongo-express-1 | basicAuth credentials are "admin:pass", it is recommended you change this in your config.js!
auth
以下、mongod が動いている方に環境変数で指定したユーザー名とパスワードでアクセスしてみたところ。期待通りユーザーが作成されている。ちなみに、mongo
だけだと何も見れないので、auth がきいてそう。
ただ、いまいち自信ないので、docker-compose.yml
にcommand: [mongod, --auth]
を追加しといた方が良いかも。本番環境では必須。
下記サイトをみると、--auth
が効いてない場合、ユーザー認証しなくても入れてしまうっぽい。
MongoDB ユーザー認証設定は必ずしましょう - Qiita
root@fdce2f3b200a:/# mongo -u root -p password
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
> use admin
switched to db admin
> show collections
system.users
system.version
> db.system.users.find()
{下記ユーザー情報}
{
"_id": "admin.root",
"userId": UUID(""),
"user": "root",
"db": "admin",
"credentials": {
"SCRAM-SHA-1": {
"iterationCount": 10000,
"salt": "",
"storedKey": "",
"serverKey": ""
},
"SCRAM-SHA-256": {
"iterationCount": 15000,
"salt": "",
"storedKey": "",
"serverKey": ""
}
},
"roles": [
{
"role": "root",
"db": "admin"
}
]
}
client の方のコンテナは、(当たり前だけど)下記の通りアクセスできない。
root@9807833c9166:/# mongo -u root -p password
MongoDB shell version v5.0.10
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Error: Authentication failed. :
connect@src/mongo/shell/mongo.js:372:17
@(connect):2:6
exception: connect failed
exiting with code 1
client のコンテナでは、下記コマンドで mongo にアクセスして情報を見れる。(当たり前だけど)system.users
はない。
root@9807833c9166:/# mongo admin
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
> use admin
switched to db admin
> show collections
system.version
クライアントから、サーバー側にアクセスするのも確認できた。host 名は mongo でいけた。
> show dbs
root@9807833c9166:/# mongo -u root -p password --host mongo
admin 0.000GB
config 0.000GB
local 0.000GB
> use admin
switched to db admin
> show collections
system.users
system.version
> db.system.users.find()
init.js
最初の立ち上げ時に実行するスクリプトを読み込ませるために、docker-compose.yml
のvolumes
に下記を追加。
- ./init.js:/docker-entrypoint-initdb.d/init.js:ro
下記init.js
を準備することで、hoge
に読み書きできるユーザーを追加することができる。
下記 Stack Overflow を信じると、init.js
でユーザー作るとき、権限周りがトリッキーなので、色々注意する必要あるみたい。色々試しても、なぜかうまくいかなくて、すごくハマった。
The tricky part was to understand that *.js files were run unauthenticated. The solution authenticates the script as the admin-user in the admin database. MONGO_INITDB_DATABASE admin is essential, otherwise the script would be executed against the test db. Check the source code of docker-entrypoint.sh.
docker - How to create a DB for MongoDB container on start up? - Stack Overflow
db = db.getSiblingDB("admin");
db.auth("root", "password");
db.createUser({
user: "testuser",
pwd: "password",
roles: [
{
role: "readWrite",
db: "hoge",
},
],
});
db = db.getSiblingDB("hoge");
db.createCollection("test");
const doc1 = { name: "Hoge", age: 36 };
const doc2 = { name: "Fuga", age: 32 };
db.test.insertMany([doc1, doc2]);
試しに接続してみたら、期待通り読み書きできた。
--authenticationDatabase
は指定したユーザーが登録されてるデータベースを指定する必要があるらしい。
今回、init.js
でルートユーザーでユーザー作成してるので、admin
に登録されるみたい。
MongoDB のユーザ管理 - Qiita
root@b0a9ed9d4807:/# mongo hoge -u testuser -p password --authenticationDatabase admin
> show dbs
hoge 0.000GB
> show collections
test
> db.test.insert({"name":"hoge"})
WriteResult({ "nInserted" : 1 })
> db.test.find()
{ "_id" : ObjectId("62fde48175962c00b516aab6"), "name" : "Hoge", "age" : 36 }
{ "_id" : ObjectId("62fde48175962c00b516aab7"), "name" : "Fuga", "age" : 32 }
{ "_id" : ObjectId("62fde64052c39d0c23eae51f"), "name" : "hoge" }
ちなみに、下記コマンドでボリューム削除しながら、何度か試した。down だけだと、ボリュームが消えなくて、データも残るから。
docker compose down --volumes
ここ参照。
docker compose down | Docker Documentation
基本操作
collection の追加削除閲覧と、Document に対する CRUD 操作を確認した。
> show collections
test
> db.createCollection("mycollection")
{ "ok" : 1 }
> show collections
mycollection
test
> db.mycollection.insert({"name":"hogehoge"});
WriteResult({ "nInserted" : 1 })
> db.mycollection.insert({"name":"fugafuga"});
WriteResult({ "nInserted" : 1 })
> db.mycollection.find();
{ "_id" : ObjectId("62fa453336a0adc30d5e2d3f"), "name" : "hogehoge" }
{ "_id" : ObjectId("62fa454736a0adc30d5e2d40"), "name" : "fugafuga" }
> db.mycollection.find({"name":"hogehoge"});
{ "_id" : ObjectId("62fa453336a0adc30d5e2d3f"), "name" : "hogehoge" }
> db.mycollection.find({"name":"hogehoge"}, {_id:0});
{ "name" : "hogehoge" }
> db.mycollection.update({"_id":ObjectId("62fa453336a0adc30d5e2d3f")}, {$set:{"name":"piyopiyo"}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
> db.mycollection.find();
{ "_id" : ObjectId("62fa453336a0adc30d5e2d3f"), "name" : "piyopiyo" }
{ "_id" : ObjectId("62fa454736a0adc30d5e2d40"), "name" : "fugafuga" }
> db.mycollection.remove({"name":"fugafuga"})
WriteResult({ "nRemoved" : 1 })
> db.mycollection.find();
{ "_id" : ObjectId("62fa453336a0adc30d5e2d3f"), "name" : "piyopiyo" }
> db.mycollection.drop();
true
> show collections
test
ここを参考にした。
MongoDB データ操作(DB, Collection, Document) - わくわく Bank
おわりに
MongoDB の基本的なところ手を動かしながら試してみた。
docker compose
で楽に環境用意できるのが素晴らしい。
ユーザー周りの挙動が、読み物だけだとよくわからなかったので、試しながらできて良かった。
次は、バックエンドから操作する部分をもうちょい試していきたい。
その他
mongosh
mongo
コマンドを使うときに、下記出力があった。今回、シンプルなコマンドしか試していないからほとんど変わらんかもやけど、今始めるなら、mongosh
てのを使った方が良いのかも。
================
Warning: the "mongo" shell has been superseded by "mongosh",
which delivers improved usability and compatibility.The "mongo" shell has been deprecated and will be removed in
an upcoming release.
For installation instructions, see
https://docs.mongodb.com/mongodb-shell/install/
================
mongo-express
mongo にアクセスする web アプリ。Node.js, Express and Bootstrap3
で作ってるらしい。
ここら参照。
mongo-express/mongo-express: Web-based MongoDB admin interface, written with Node.js and express
mongo-express - Official Image | Docker Hub
mongodb を GUI で。mongo-express - Qiita
参考
他に参考にしたところは下記の通り。
Discussion