docker-composeを使ってレプリカセットでmongoDBを起動する
Updated Date: 2024/01/01 02:55
MongoDBのバージョンが4、5、6とあったりレプリケーションでのローカル起動の方法が色々あったり、正しい情報を探すのにとても苦労したので、 ここにdocker-composeを使ってmongoDBをレプリカセットで起動する方法をメモしておく。 ちなみになぜレプリカセットで起動したいのかというと、MongoDBの Change Streams を使いたいたかったからである。
最初にまとめ
最初にdocker-compose周りのディレクトリ構成を示す。
1
2
3
4
5
6
.
├── docker
│ └── db
│ └── init
│ └── init.js
└── docker-compose.yml
次に作成するdocker-compose.ymlは以下のようになる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
version: '3'
services:
mongo:
image: mongo:6.0.6
environment:
- AUTH=no
command: [--replSet, my-replica-set, --noauth, --bind_ip_all]
ports:
- 27017:27017
healthcheck:
#test: test $$(mongosh --port 27017 --quiet --eval "try {rs.initiate({_id:'my-replica-set',members:[{_id:0,host:\"mongo:27017\"}]})} catch(e) {rs.status().ok}") -eq 1
test: mongosh mongo-init.js
interval: 10s
start_period: 30s
volumes:
- mongodb_data:/data/db
#- ./docker/db/init/:/docker-entrypoint-initdb.d/:ro
- ./docker/db/init/db_init.js:/mongo-init.js
restart: always
mongo-express:
image: mongo-express
container_name: mongo_express
restart: always
ports:
- 8081:8081
environment:
#ME_CONFIG_MONGODB_URL: mongodb://@mongo:27017/
ME_CONFIG_MONGODB_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: password
ME_CONFIG_MONGODB_SERVER: mongo
ME_CONFIG_MONGODB_PORT: 27017
depends_on:
- mongo
# mongodbのデータはdocker volumeで管理されるので、消すときは docker volume rm mongodb_data
volumes:
mongodb_data:
上記docker-compose.ymlに記載のある起動用のスクリプトも作成する。これはmongoDBのレプリカセットを初期化するためのものである。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
init = false;
print("Init script ...")
try {
if (!db.isMaster().ismaster) {
print("Error: primary not ready, initialize ...")
rs.initiate(
{
_id:'my-replica-set',
members: [
{ _id:0,
host: "mongo:27017"
}
]
}
)
quit(1);
} else {
if (!init) {
admin = db.getSiblingDB("admin");
admin.createUser(
{
user: "root",
pwd: "password",
roles: ["readWriteAnyDatabase"]
}
);
init = true;
}
}
} catch(e) {
rs.status().ok
}
以上でdocker-composeを使ってmongoDBをレプリカセットで起動することができる。
次章より簡単にどういう実装内容なのかをまとめる。
MongoDB
まず利用するMongoDBはバージョン6.0.6を利用。レプリケーションを利用したいので --replSet
オプションをつけて起動する。
今回はローカルでの開発用なので最小構成としてプライマリーノードを1つだけ起動する。本来は3台構成で起動するのが望ましい。
--bind_ip_all
はローカルでの開発用として外部からの接続を許可するためにつけている。
また、レプリカセットの初期化を行うために healthcheck
にてスクリプトを監視するようにしている。
MongoDBのコンテナイメージはレプリカセット起動をすると、entrypoint-initdb.dにあるスクリプトを実行してくれない。
この問題(仕様)により、レプリカセットの初期化やユーザーの作成を行うためにハック的に healthcheck
でスクリプトを実行するようにしている。
考えた人は天才だと思う。
スクリプト内で作成している管理ユーザーはmongo-express(GUIでMongoDBを操作できるアプリ)と自前のWebアプリのために作成している。
この設定によりわざわざ認証鍵を生成・指定する必要がなくなる。
volumes
をdocker volumeにしている理由は、パーミッションの問題で動かなかったため。
また上述通りコンテナの初回起動時レプリカセットが起動するタイミングでhealthcheckは必ずコケるため、 restart: always
をつけている。
- https://n-laboratory.jp/articles/mongodb-replicaset-docker
- https://github.com/docker-library/mongo/issues/339
mongo-express
mongo-expressはmongoDBのGUIクライアントである。mongoDBの操作をGUIで行いたい場合に利用する。
environment
を使うことでmongoDBの接続先を指定することができるので便利。
このコンテナを使いたいがために色々docker-composeの記述方法を調べていたといっても過言ではない。
おわりに
docker-composeを使ってmongoDBをレプリカセットで起動する方法をまとめた。
ここまで簡単・単純にまとまった記事は(僕が探した範囲では)なかったので、今後同じようなことをする人の参考になれば幸いである。
多分MongoDBのバージョンが上がるとまた色々変わると思うので、その時はまた記事を書くかもしれない。