paint-brush
MongoDB 和 Docker-Compose:如何自动启用自定义用户和密码经过@tiago-melo
17,270 讀數
17,270 讀數

MongoDB 和 Docker-Compose:如何自动启用自定义用户和密码

经过 Tiago Melo7m2023/05/09
Read on Terminal Reader

太長; 讀書

[MongoDB](http://mongodb.com/) 是一个广泛使用的数据库管理系统。默认情况下不启用身份验证功能。这意味着用户将需要提供有效的凭据(用户名和密码)才能访问数据库。我们将看到如何启用身份验证并通过 [docker-compose] 自动创建自定义用户/密码
featured image - MongoDB 和 Docker-Compose:如何自动启用自定义用户和密码
Tiago Melo HackerNoon profile picture

MongoDB是一种广泛使用的NoSQL数据库管理系统,它提供了多种特性,例如可扩展性、高性能和灵活性。


但是,用户在设置MongoDB时需要记住的一个重要方面是默认情况下不启用身份验证功能。


这意味着当您使用docker-composeMongoDB创建新容器时,您将需要手动启用身份验证以确保只有授权用户才能访问数据库。


但是使用docker-compose等工具设置外部依赖项的全部意义在于尽可能自动化一切以节省宝贵的时间。


在这篇快速文章中,我们将看到如何启用身份验证并通过docker-compose自动创建自定义用户/密码。

示例项目

我将展示一个用Go编写的示例项目:



  • 使用Javascript为给定的数据库创建自定义用户和密码;


  • 使用上述凭据连接到MongoDB实例。

docker-compose.yaml

 version: "3.9" services: mongodb: container_name: mongodb-sample image: mongo:latest restart: always ports: - "27017:27017" volumes: - mongodb-data:/data/db - ./db/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js env_file: - .env command: [--auth] volumes: mongodb-data:


Docker Compose文件中, command键用于指定容器启动时应在容器内运行的命令。对于MongoDB容器,命令密钥的一种常见用途是通过将--auth选项传递给mongod进程来启用身份验证。


--auth选项传递给 mongod 进程时,它会启用对MongoDB实例的身份验证。这意味着用户将需要提供有效的凭据(用户名和密码)才能访问数据库。


如果没有身份验证,任何有权访问MongoDB实例的人都可能访问、修改或删除敏感数据,这可能会导致严重的安全漏洞。


我们通过运行将db/mongo-init.js文件复制到容器中- ./db/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js。

MongoDB JavaScript 用户/通行证创建文件

数据库/mongo-init.js

 db = db.getSiblingDB('sample_db') db.createUser({ user: 'some_user', pwd: 'random_pass', roles: [ { role: 'dbOwner', db: 'sample_db', }, ], });


生成文件

SHELL = /bin/bash DOCKER_MONGODB=docker exec -it mongodb-sample mongosh -u $(ADMIN_USER) -p $(ADMIN_PASSWORD) --authenticationDatabase admin DOCKER_MONGODB_WITH_CUSTOM_CREDS=docker exec -it mongodb-sample mongosh -u $(DB_USER) -p $(DB_PASS) --authenticationDatabase $(DB_NAME) .PHONY: help ## help: shows this help message help: @ echo "Usage: make [target]" @ sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /' .PHONY: setup-db ## setup-db: sets up MongoDB setup-db: export ADMIN_USER=admin setup-db: export ADMIN_PASSWORD=f3MdBEcz setup-db: @ echo "Setting up MongoDB..." @ docker-compose up -d mongodb @ until $(DOCKER_MONGODB) --eval 'db.getUsers()' >/dev/null 2>&1 && exit 0; do \ >&2 echo "MongoDB not ready, sleeping for 5 secs..."; \ sleep 5 ; \ done @ echo "... MongoDB is up and running!" .PHONY: mongodb-console ## mongodb-console: opens MongoDB console mongodb-console: export DB_USER=some_user mongodb-console: export DB_PASS=random_pass mongodb-console: export DB_NAME=sample_db mongodb-console: @ ${DOCKER_MONGODB_WITH_CUSTOM_CREDS} .PHONY: run ## run: runs the application run: setup-db @ go run cmd/main.go .PHONY: cleanup ## cleanup: removes MongoDB and associated volumes cleanup: @ docker-compose down @ docker volume rm $$(docker volume ls -q) .PHONY: test ## test: runs unit tests test: @ go test -v ./...


run目标调用的setup-db目标不断尝试连接到MongoDB ,以便Go主程序可以安全地尝试连接到它。

连接到 MongoDB


.env

 MONGO_INITDB_ROOT_USERNAME=admin MONGO_INITDB_ROOT_PASSWORD=f3MdBEcz MONGODB_DATABASE=sample_db MONGODB_USER=some_user MONGODB_PASSWORD=random_pass MONGODB_HOST_NAME=localhost MONGODB_PORT=27017


配置/config.go

 // Copyright (c) 2023 Tiago Melo. All rights reserved. // Use of this source code is governed by the MIT License that can be found in // the LICENSE file. package config import ( "github.com/joho/godotenv" "github.com/kelseyhightower/envconfig" "github.com/pkg/errors" ) // Config holds all configuration needed by this app. type Config struct { MongoDbUser string `envconfig:"MONGODB_USER"` MongoDbPassword string `envconfig:"MONGODB_PASSWORD"` MongoDbDatabase string `envconfig:"MONGODB_DATABASE"` MongoDbHostName string `envconfig:"MONGODB_HOST_NAME"` MongoDbPort int `envconfig:"MONGODB_PORT"` } var ( godotenvLoad = godotenv.Load envconfigProcess = envconfig.Process ) func ReadConfig() (*Config, error) { if err := godotenvLoad(); err != nil { return nil, errors.Wrap(err, "loading env vars") } config := new(Config) if err := envconfigProcess("", config); err != nil { return nil, errors.Wrap(err, "processing env vars") } return config, nil }


数据库/mongodb.go

 // Copyright (c) 2023 Tiago Melo. All rights reserved. // Use of this source code is governed by the MIT License that can be found in // the LICENSE file. package db import ( "context" "fmt" "github.com/pkg/errors" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) type MongoDb struct { database string client *mongo.Client } // For ease of unit testing. var ( connect = func(ctx context.Context, client *mongo.Client) error { return client.Connect(ctx) } ping = func(ctx context.Context, client *mongo.Client) error { return client.Ping(ctx, nil) } ) // ConnectToMongoDb connects to a running MongoDB instance. func ConnectToMongoDb(ctx context.Context, user, pass, host, database string, port int) (*MongoDb, error) { client, err := mongo.NewClient(options.Client().ApplyURI( uri(user, pass, host, database, port), )) if err != nil { return nil, errors.Wrap(err, "failed to create MongoDB client") } err = connect(ctx, client) if err != nil { return nil, errors.Wrap(err, "failed to connect to MongoDB server") } err = ping(ctx, client) if err != nil { return nil, errors.Wrap(err, "failed to ping MongoDB server") } return &MongoDb{ database: database, client: client, }, nil } // uri generates uri string for connecting to MongoDB. func uri(user, pass, host, database string, port int) string { const format = "mongodb://%s:%s@%s:%d/%s" return fmt.Sprintf(format, user, pass, host, port, database) }


命令/main.go

 // Copyright (c) 2023 Tiago Melo. All rights reserved. // Use of this source code is governed by the MIT License that can be found in // the LICENSE file. package main import ( "context" "fmt" "os" "github.com/pkg/errors" "github.com/tiagomelo/docker-mongodb-custom-user-pass/config" "github.com/tiagomelo/docker-mongodb-custom-user-pass/db" ) func run() error { ctx := context.Background() config, err := config.ReadConfig() if err != nil { return errors.Wrap(err, "reading config") } _, err = db.ConnectToMongoDb(ctx, config.MongoDbUser, config.MongoDbPassword, config.MongoDbHostName, config.MongoDbDatabase, config.MongoDbPort, ) if err != nil { return errors.Wrap(err, "connecting to MongoDB") } fmt.Println("successfully connected to MongoDB.") return nil } func main() { if err := run(); err != nil { fmt.Println(err) os.Exit(1) } }


运行它

$ make run Setting up MongoDB.. [+] Running 3/3 ⠿ Network docker-mongodb-custom-user-pass_default Created 0.0s ⠿ Volume "docker-mongodb-custom-user-pass_mongodb-data" Created 0.0s ⠿ Container mongodb-sample Started 0.3s MongoDB not ready, sleeping for 5 secs... ... MongoDB is up and running! successfully connected to MongoDB..


“成功连接到MongoDB”。消息指出我们能够连接到它。

MongoDB 外壳访问

$ make mongodb-console Current Mongosh Log ID: 645955b82bcce4a09d59bda3 Connecting to: mongodb://<credentials>@127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&authSource=sample_db&appName=mongosh+1.8.2 Using MongoDB: 6.0.5 Using Mongosh: 1.8.2 For mongosh info see: https://docs.mongodb.com/mongodb-shell/ test> use sample_db switched to db sample_db sample_db>


下载源代码

这里:https: //github.com/tiagomelo/docker-mongodb-custom-user-pass