MongoDB и Docker-Compose: как автоматически включить пользовательского пользователя и пароль

MongoDB и Docker-Compose: как автоматически включить пользовательского пользователя и пароль

9 мая 2023 г.

MongoDB — это широко используемый NoSQL система управления базами данных, которая предлагает несколько функций, таких как масштабируемость, высокая производительность и гибкость.

Однако при настройке MongoDB пользователи должны помнить об одном важном аспекте: функция проверки подлинности не включена по умолчанию.

Это означает, что при создании нового контейнера для MongoDB с помощью docker-compose, вам потребуется включить аутентификацию вручную, чтобы гарантировать, что только авторизованные пользователи имеют доступ к базе данных.

Но весь смысл настройки внешних зависимостей с помощью таких инструментов, как docker-compose, заключается в том, чтобы максимально все автоматизировать, чтобы сэкономить драгоценное время. .

В этой краткой статье мы увидим, как включить аутентификацию и автоматически создать пользователя/пароль с помощью docker-compose.< /p>

Пример проекта

Я покажу пример проекта, написанного на Go, который:

* использует docker-compose для предоставления MongoDB экземпляр;

* используйте 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 ./...

Цель setup-db, которая вызывается целью run, продолжает пытаться подключиться к MongoDB< /a>, чтобы основная программа Go могла безопасно подключиться к нему.

Подключение к MongoDB

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

n config/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..

«Успешное подключение к 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.


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE