docker-composeでMongoDBをレプリカセット起動する【完全版・6.0対応】
Updated Date: 2026/03/04 23:14
MongoDBのバージョン差異・レプリカセット起動の複雑さ・entrypoint-initdb.d が動かない問題など、正確な情報を探すのにとても苦労したのでまとめておく。
なぜレプリカセットで起動するのか? → Change Streams を使いたいから。Change Streamsはレプリカセット構成でないと動作しない。
TL;DR(結論から)
完成形のファイル構成はこちら:
1
2
3
4
5
6
.
├── docker
│ └── db
│ └── init
│ └── db_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
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: mongosh mongo-init.js
interval: 10s
start_period: 30s
volumes:
- mongodb_data:/data/db
- ./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_ADMINUSERNAME: root
ME_CONFIG_MONGODB_ADMINPASSWORD: password
ME_CONFIG_MONGODB_SERVER: mongo
ME_CONFIG_MONGODB_PORT: 27017
depends_on:
- mongo
volumes:
mongodb_data:
レプリカセット初期化スクリプト(db_init.js)
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
}
起動方法
1
docker-compose up -d
起動後、 http://localhost:8081 でmongo-expressのGUI管理画面にアクセスできる。
ログインのユーザー名・パスワードはデフォルトで admin / pass。
接続文字列(アプリから接続する場合)
1
mongodb://root:password@localhost:27017/?authSource=admin&replicaSet=my-replica-set
レプリカセットを使う場合、replicaSet=my-replica-set の指定が必要な点に注意。
データの削除
1
2
# コンテナとボリュームをまとめて削除
docker-compose down -v
mongodb_data はdocker volumeで管理されているため、docker volume rm mongodb_data でも削除できる。
なぜこの構成にしたか(詳細解説)
MongoDBコンテナのポイント
--replSet my-replica-set オプションをつけて起動することでレプリカセットが有効になる。今回はローカル開発用なので最小構成のプライマリーノード1台のみ。本番環境では3台構成が推奨。
--bind_ip_all はローカル開発用に外部からの接続を許可するためのオプション。本番では使わないこと。
entrypoint-initdb.d が動かない問題と healthcheck ハック
MongoDBのコンテナイメージは レプリカセット付きで起動すると docker-entrypoint-initdb.d/ に配置したスクリプトを実行してくれない という仕様がある。
これはMongoDBのissueでも長く議論されている問題で、回避策として healthcheck でスクリプトを実行するハックが考案されている。仕組みはこうだ:
- コンテナ起動直後、レプリカセット初期化前は
healthcheckが必ずコケる restart: alwaysにより自動再起動がかかる- 再起動のたびに
db_init.jsが実行され、レプリカセット初期化を試みる - 初期化が成功すると
healthcheckが通るようになり、安定動作に入る
これが restart: always をつけている理由。
volumesをdocker volumeにした理由
バインドマウント(ホストのディレクトリを直接マウント)にするとLinux環境でパーミッションエラーが出やすいため、named volume(mongodb_data)を使っている。
mongo-expressとは
MongoDBのGUIクライアント。ブラウザからコレクションの閲覧・編集・クエリ実行ができる。environment で接続先を設定できるので、ローカル開発時のデバッグに便利。
よくあるトラブルと対処
「レプリカセットの初期化が終わらない / ずっとrestartしている」
→ start_period: 30s を伸ばしてみる。マシンスペックによっては初回起動に時間がかかる。
「アプリから接続するとエラーになる」
→ 接続文字列に replicaSet=my-replica-set が入っているか確認。これがないとChange Streamsが使えない。
「mongo-expressにアクセスできない」
→ mongoDBコンテナのhealthcheckが通過するまでmongo-expressが起動しない(depends_on)。少し待ってからアクセスする。
参考にしたサイト: