1. 概述

MongoDB 是一款流行的 NoSQL 数据库,以灵活处理非结构化数据著称。在使用 Docker 容器部署时,我们常常希望在容器启动时就完成数据库和用户的初始化,以简化部署流程并确保环境一致性。

本文将介绍几种在 Docker 中自动初始化 MongoDB 的方法,包括:

  • 使用 Docker Compose + JS 初始化脚本
  • 使用 Shell 脚本初始化
  • 自定义 Dockerfile 构建镜像

适合希望快速部署 MongoDB 容器并自动完成初始化配置的开发者或运维人员。


2. 使用 Docker Compose 初始化 MongoDB

Docker Compose 是快速构建容器化服务的利器。我们可以通过它定义 MongoDB 容器,并在启动时自动创建数据库和用户。

2.1. 编写 docker-compose.yml 文件

以下是一个典型的 docker-compose.yml 配置示例:

version: '5.0'

services:
    mongodb:
        image: mongo:latest
        container_name: mongodb
        restart: always
        environment:
            MONGO_INITDB_ROOT_USERNAME: admin
            MONGO_INITDB_ROOT_PASSWORD: password
            MONGO_INITDB_DATABASE: mydatabase
        ports:
            - 27017:27017
        volumes:
            - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

说明:

  • 使用 mongo:latest 镜像
  • 设置容器名为 mongodb
  • 初始化 root 用户 admin 和密码 password,默认数据库为 mydatabase
  • 映射宿主机端口 27017 到容器端口
  • 将 JS 初始化脚本挂载到容器指定目录 /docker-entrypoint-initdb.d/,该目录下的脚本会在 MongoDB 初始化时自动执行

注意MONGO_INITDB_ROOT_USERNAMEMONGO_INITDB_ROOT_PASSWORD 是 MongoDB 官方镜像支持的环境变量,用于设置管理员账户。

2.2. 编写初始化脚本 mongo-init.js

创建 mongo-init.js 文件,内容如下:

db.createUser({
    user: "dbuser",
    pwd: "dbpassword",
    roles: [{
        role: "readWrite",
        db: "mydatabase"
    }]
});

这个脚本会在容器启动时自动执行,创建一个名为 dbuser 的用户,并赋予 mydatabase 数据库的 readWrite 权限。

2.3. 启动 MongoDB 容器

执行以下命令启动容器:

docker-compose up --build -d mongodb

输出示例:

[+] Running 9/9
 ✔ mongodb 8 layers [⣿⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                                                     225.1s 
...
 ✔ Container mongodb                  Started

⚠️ 注意:首次运行时会拉取镜像,可能耗时较长。后续运行会直接使用本地镜像。

2.4. 验证初始化是否成功

进入 MongoDB Shell 进行验证:

mongo --host localhost --port 27017 -u admin -p password --authenticationDatabase admin

切换到 mydatabase 并查看用户:

use mydatabase;
db.getUsers();

输出示例:

[
    {
        "_id" : "mydatabase.dbuser",
        "user" : "dbuser",
        "roles" : [
            {
                "role" : "readWrite",
                "db" : "mydatabase"
            }
        ]
    }
]

说明:用户和数据库已成功初始化。


3. 使用 Shell 脚本初始化 MongoDB

在某些场景下,使用 Shell 脚本进行初始化会更灵活,尤其是需要动态传入参数时。

3.1. 编写 init-mongo.sh 脚本

#!/bin/bash

MONGO_USER="user"
MONGO_PASSWORD="userpasswd"

q_MONGO_USER=$(jq --arg v "$MONGO_USER" -n '$v')
q_MONGO_PASSWORD=$(jq --arg v "$MONGO_PASSWORD" -n '$v')

mongo -u "$MONGO_INITDB_ROOT_USERNAME" -p "$MONGO_INITDB_ROOT_PASSWORD" admin <<EOF
    use mydatabase;
    db.createUser({
        user: $q_MONGO_USER,
        pwd: $q_MONGO_PASSWORD,
        roles: ["readWrite"],
    });
EOF

说明:

  • 使用 jq 工具对用户名和密码进行 JSON 格式转义
  • 通过 mongo 命令连接 MongoDB,创建用户

⚠️ 注意:确保容器内安装了 jq,否则脚本会报错。

3.2. 修改 docker-compose.yml 文件

将 Shell 脚本挂载到容器指定目录:

volumes:
  - ./init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh:ro

注意:只要脚本放在 /docker-entrypoint-initdb.d/ 目录下,MongoDB 官方镜像会自动执行它。

3.3. 启动容器并验证

使用相同命令启动容器:

docker-compose up --build -d mongodb

验证方式同上,使用 db.getUsers() 查看用户是否创建成功。


4. 使用自定义 Dockerfile 初始化 MongoDB

如果你希望构建一个包含初始化逻辑的自定义 MongoDB 镜像,可以使用 Dockerfile。

4.1. 编写 Dockerfile

FROM mongo:latest

ENV MONGO_INITDB_ROOT_USERNAME=admin
ENV MONGO_INITDB_ROOT_PASSWORD=password

COPY mongo-init.js /docker-entrypoint-initdb.d/

说明:

  • 继承官方 mongo:latest 镜像
  • 设置 root 用户和密码
  • mongo-init.js 拷贝到初始化目录

4.2. 创建初始化脚本 mongo-init.js

db.createUser({
    user: "user",
    pwd: "userpasswd",
    roles: [
        { role: "readWrite", db: "mydatabase" }
    ]
});

4.3. 构建自定义镜像

docker build -t custom-mongo .

输出示例:

Successfully built 37eb14b2bd41
Successfully tagged custom-mongo:latest

4.4. 运行自定义容器

docker run -d --name mongodb -p 27017:27017 custom-mongo

此时容器已启动并完成初始化。


5. 总结

本文介绍了三种常见的 MongoDB 容器初始化方式:

方法 优点 适用场景
Docker Compose + JS 脚本 简洁明了,易维护 快速搭建开发环境
Shell 脚本 灵活,支持动态参数 复杂初始化逻辑
自定义 Dockerfile 镜像固化,适合部署 生产环境镜像构建

建议

  • 开发阶段推荐使用 Docker Compose + JS 脚本,快速验证初始化逻辑
  • 如果需要动态参数,使用 Shell 脚本更合适
  • 生产部署建议使用自定义 Dockerfile 构建镜像,确保一致性

通过这些方法,你可以轻松实现 MongoDB 容器的自动化初始化,提升部署效率。


原始标题:Create MongoDB Container on Startup