Docker容器JS入口文件使用MongoDB加密模块遇问题求助
解决Docker容器MongoDB初始化脚本中插入加密字段文档的问题
问题根源
你当前使用的MongoDB容器初始化JS脚本是运行在MongoDB内置的mongosh(或mongo shell)环境中,并非Node.js环境,所以:
- 无法使用Node.js驱动的
MongoClient类 - 不能用
require('mongodb')这种Node.js模块引入语法,容器里根本没装这些Node.js包
方案一:使用mongosh原生语法实现客户端字段加密
直接在mongosh环境中配置加密并插入文档,无需依赖Node.js模块:
// 从环境变量获取认证信息 const rootUsername = process.env.MONGO_INITDB_ROOT_USERNAME; const rootPassword = process.env.MONGO_INITDB_ROOT_PASSWORD; const dbName = process.env.MONGO_INITDB_DATABASE; // 连接到admin库认证,再切换到目标库 const adminDb = connect(`mongodb://${rootUsername}:${rootPassword}@localhost:27017/admin`); const db = adminDb.getSiblingDB(dbName); // 1. 配置客户端加密(以本地KMS为例,适合测试环境) const kmsProviders = { local: { key: BinData(0, "Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk"), }, }; const clientEncryption = db.getMongo().getClientEncryption({ keyVaultNamespace: "encryption.__keyVault", kmsProviders: kmsProviders, }); // 2. 创建数据加密密钥(DEK) const dataKeyId = clientEncryption.createDataKey("local"); // 3. 定义加密集合的 schema,指定需要加密的字段 const encryptedFieldsMap = { [dbName]: { yourCollectionName: { fields: [ { keyId: dataKeyId, path: "sensitiveField", // 需要加密的字段名 bsonType: "string", queries: { queryType: "equality" }, }, ], }, }, }; // 4. 创建带加密配置的集合 db.createCollection("yourCollectionName", { encryptedFields: encryptedFieldsMap[dbName].yourCollectionName, }); // 5. 插入包含加密字段的文档 db.yourCollectionName.insertOne({ normalField: "普通内容", sensitiveField: "需要加密的敏感内容", });
方案二:自定义Docker镜像,使用Node.js脚本初始化
如果必须使用Node.js的mongodb和mongodb-client-encryption模块(比如复杂加密逻辑),需要自定义镜像:
- 创建
Dockerfile:
FROM mongo:latest # 安装Node.js和npm RUN apt-get update && apt-get install -y nodejs npm # 安装所需Node.js模块 RUN npm install mongodb mongodb-client-encryption # 将你的Node.js初始化脚本复制到容器 COPY init-mongo.js /docker-entrypoint-initdb.d/ # 修改脚本执行命令为node RUN chmod +x /docker-entrypoint-initdb.d/init-mongo.js
- 编写Node.js版本的
init-mongo.js:
const { MongoClient } = require('mongodb'); const { ClientEncryption } = require('mongodb-client-encryption'); async function init() { const rootUsername = process.env.MONGO_INITDB_ROOT_USERNAME; const rootPassword = process.env.MONGO_INITDB_ROOT_PASSWORD; const dbName = process.env.MONGO_INITDB_DATABASE; const uri = `mongodb://${rootUsername}:${rootPassword}@localhost:27017/${dbName}?authSource=admin`; // 配置加密选项 const kmsProviders = { local: { key: Buffer.from("Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk", "base64"), }, }; const client = new MongoClient(uri, { autoEncryption: { keyVaultNamespace: "encryption.__keyVault", kmsProviders: kmsProviders, }, }); await client.connect(); const db = client.db(dbName); // 创建数据加密密钥 const clientEncryption = new ClientEncryption(client, { keyVaultNamespace: "encryption.__keyVault", kmsProviders: kmsProviders, }); const dataKeyId = await clientEncryption.createDataKey("local"); // 创建加密集合 await db.createCollection("yourCollectionName", { encryptedFields: { fields: [ { keyId: dataKeyId, path: "sensitiveField", bsonType: "string", queries: { queryType: "equality" }, }, ], }, }); // 插入加密文档 await db.yourCollectionName.insertOne({ normalField: "普通内容", sensitiveField: "敏感加密内容", }); await client.close(); } init().catch(err => console.error(err));
- 构建并运行自定义镜像:
docker build -t mongo-encrypted . docker run -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=password -e MONGO_INITDB_DATABASE=testdb mongo-encrypted
内容的提问来源于stack exchange,提问作者Aleksandr
相关产品推荐
相关产品推荐

