You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

容器启动时如何为MongoDB单节点副本集初始化数据

MongoDB单节点副本集自动初始化数据方案

问题背景

此前使用独立MongoDB实例,通过Docker Compose、自定义Dockerfile及导入脚本,可在容器启动时自动用./db/seed目录下的JSON文件初始化数据,但该架构无法使用MongoDB事务。

为启用事务,搭建了单节点副本集,通过healthcheck机制初始化副本集,但这导致导入脚本与副本集初始化存在竞态条件——数据导入时副本集未就绪引发错误,容器停止。

需求是无需手动执行mongoimport,仅通过docker compose up就能完成副本集的数据初始化并就绪。最终采用单独的mongo_seeder服务,依赖健康检查完成后的mongo服务,实现自动数据导入,无需再使用自定义Dockerfile。


原独立实例配置

Docker Compose配置

database:
    build:
      context: .
      dockerfile: ./db/Dockerfile.mongodb
    ports:
      - 12000:27017
    volumes:
      - ./data/data:/data/db
    environment:
      - MONGO_INITDB_DATABASE=DB

自定义Dockerfile(./db/Dockerfile.mongodb)

FROM mongo:latest

COPY ./db/seed /import
COPY ./db/import/import.sh /docker-entrypoint-initdb.d/
RUN chmod 777 /docker-entrypoint-initdb.d/import.sh

导入脚本(./db/import/import.sh)

#!/bin/bash
for f in /import/*.json
do
    name=$(basename $f | cut -d'.' -f1)
    mongoimport --db=DB --collection=$name --jsonArray --file=$f
done

单节点副本集初始配置(存在竞态问题)

Docker Compose配置

services:
  mongo:
    build:
      context: .
      dockerfile: ./db/Dockerfile.mongodb
    command: [--replSet, rs0, --bind_ip_all, --port, "12000"]
    ports:
      - 12000:12000
    environment:
      - MONGO_INITDB_DATABASE=DB
    healthcheck:
      test: test $$(mongosh --port 12000 --quiet --eval "try {rs.initiate({_id:'rs0',members:[{_id:0,host:\"mongo:12000\"}]})} catch(e) {rs.status().ok}") -eq 1
      interval: 10s
      start_period: 0s

导入脚本(./db/import/import.sh)

#!/bin/bash

for f in /import/*.json
do
    name=$(basename $f | cut -d'.' -f1)
    mongoimport --host=rs0/0.0.0.0:12000 --db=DB --collection=$name --jsonArray --file=$f
done

此配置中,导入脚本随MongoDB容器启动执行,但副本集初始化依赖healthcheck异步完成,存在竞态条件,导致导入时副本集未就绪,容器报错停止。


最终解决方案配置

Docker Compose配置

services:
  mongo:
    image: mongo:latest
    command: [--replSet, rs0, --bind_ip_all, --port, "12000"]
    ports:
      - 12000:12000
    environment:
      - MONGO_INITDB_DATABASE=DB
    healthcheck:
      test: test $$(mongosh --port 12000 --quiet --eval "try {rs.initiate({_id:'rs0',members:[{_id:0,host:\"mongo:12000\"}]})} catch(e) {rs.status().ok}") -eq 1
      interval: 10s
      start_period: 0s
  mongo_seeder:
    image: mongo:latest
    depends_on:
      mongo:
        condition: service_healthy
    volumes:
      - ./tools/db:/tmp/db/
    environment:
      - MONGO_INITDB_DATABASE=DB
      - MONGOIMPORT_HOST_STRING=rs0/mongo:12000
    command: bash /tmp/db/import/import.sh

导入脚本(./tools/db/import/import.sh)

#!/bin/bash

for f in /tmp/db/seed/*.json
do
    name=$(basename $f | cut -d'.' -f1)
    mongoimport --host=$MONGOIMPORT_HOST_STRING --db=$MONGO_INITDB_DATABASE --collection=$name --jsonArray --file=$f
done

核心改进:

  • 拆分出独立的mongo_seeder服务,使用官方Mongo镜像,无需自定义Dockerfile
  • 通过depends_on的service_healthy条件,确保仅在Mongo副本集健康检查通过(即副本集就绪)后才执行数据导入
  • 导入脚本通过环境变量配置连接信息,更灵活

内容的提问来源于stack exchange,提问作者user23145140

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 01:15:08