MongoDB là một hệ thống quản lý cơ sở dữ liệu NoSQL được sử dụng rộng rãi, cung cấp một số tính năng như khả năng mở rộng, hiệu suất cao và tính linh hoạt.
Tuy nhiên, một khía cạnh quan trọng mà người dùng cần lưu ý khi thiết lập MongoDB là tính năng xác thực không được bật theo mặc định.
Điều này có nghĩa là khi bạn tạo vùng chứa mới cho MongoDB bằng cách sử dụng docker-compose , bạn sẽ cần bật xác thực theo cách thủ công để đảm bảo rằng chỉ những người dùng được ủy quyền mới có quyền truy cập vào cơ sở dữ liệu.
Nhưng toàn bộ quan điểm của việc thiết lập các phụ thuộc bên ngoài bằng các công cụ như docker-compose là tự động hóa mọi thứ nhiều nhất có thể để tiết kiệm thời gian quý báu.
Trong bài viết nhanh này, chúng ta sẽ xem cách bật xác thực và tự động tạo một người dùng/vượt qua tùy chỉnh thông qua docker-compose .
Tôi sẽ hiển thị một dự án mẫu được viết bằng Go :
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:
Trong tệp Docker Compose , phím lệnh được sử dụng để chỉ định lệnh sẽ chạy bên trong vùng chứa khi nó khởi động. Đối với bộ chứa MongoDB , một cách sử dụng phổ biến của phím lệnh là kích hoạt xác thực bằng cách chuyển tùy chọn --auth cho quy trình mongod .
Khi tùy chọn --auth được chuyển đến quy trình mongod, nó sẽ kích hoạt xác thực cho phiên bản MongoDB . Điều này có nghĩa là người dùng sẽ cần cung cấp thông tin đăng nhập hợp lệ (tên người dùng và mật khẩu) để truy cập cơ sở dữ liệu.
Nếu không có xác thực, bất kỳ ai có quyền truy cập vào phiên bản MongoDB đều có thể truy cập, sửa đổi hoặc xóa dữ liệu nhạy cảm, điều này có thể dẫn đến vi phạm bảo mật nghiêm trọng.
Chúng tôi đang sao chép tệp db/mongo-init.js vào bộ chứa bằng cách chạy - ./db/mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js.
db/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 ./...
Mục tiêu setup-db , được gọi bởi mục tiêu chạy , tiếp tục cố gắng kết nối với MongoDB để chương trình Go chính có thể thử kết nối với nó một cách an toàn.
.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
cấu hình/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 }
db/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) }
cmd/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..
Thông báo "đã kết nối thành công với MongoDB." thông báo nói rằng chúng tôi có thể kết nối với nó.
$ 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>
Tại đây: https://github.com/tiagomelo/docker-mongodb-custom-user-pass