Estoy trabajando con Docker y tengo una pila con PHP, MySQL, Apache y Redis. Necesito agregar MongoDB ahora, así que estaba verificando el Dockerfile para la última versión y también el archivo docker-entrypoint.sh del MongoDB Dockerhub, pero no pude encontrar una manera de configurar una base de datos predeterminada, usuario / contraseña de administrador y posiblemente autenticación método para el contenedor desde un docker-compose.yml
archivo.
En MySQL puede configurar algunas variables ENV como por ejemplo:
db:
image: mysql:5.7
env_file: .env
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
Y esto configurará la base de datos y el usuario / contraseña como root
contraseña.
¿Hay alguna forma de lograr lo mismo con MongoDB? ¿Alguien tiene alguna experiencia o solución?
mongodb
docker
docker-compose
ReynierPM
fuente
fuente
Respuestas:
La imagen oficial se
mongo
ha fusionado con un PR para incluir la funcionalidad para crear usuarios y bases de datos al inicio.La inicialización de la base de datos se ejecutará cuando no haya nada en el
/data/db
directorio.Configuración de usuario administrador
Las variables de entorno para controlar la configuración del usuario "root" son
MONGO_INITDB_ROOT_USERNAME
MONGO_INITDB_ROOT_PASSWORD
Ejemplo
No necesita / no puede usar
--auth
en la línea de comando ya que el script docker entrypoint.sh agrega esto cuando existen las variables de entorno.Inicialización de la base de datos
La imagen también proporciona la
/docker-entrypoint-initdb.d/
ruta para implementar scripts de configuración.js
o personalizados.sh
que se ejecutarán una vez en la inicialización de la base de datos..js
Los scripts se ejecutarántest
de forma predeterminada oMONGO_INITDB_DATABASE
si están definidos en el entorno.o
Un archivo javascript simple de inicialización mongo shell que demuestra cómo configurar la
container
colección con datos, registro y cómo salir con un error (para la verificación de resultados)let error = true let res = [ db.container.drop(), db.container.createIndex({ myfield: 1 }, { unique: true }), db.container.createIndex({ thatfield: 1 }), db.container.createIndex({ thatfield: 1 }), db.container.insert({ myfield: 'hello', thatfield: 'testing' }), db.container.insert({ myfield: 'hello2', thatfield: 'testing' }), db.container.insert({ myfield: 'hello3', thatfield: 'testing' }), db.container.insert({ myfield: 'hello3', thatfield: 'testing' }), db.other. ] printjson(res) if (error) { print('Error, exiting') quit(1) }
fuente
set -e
está diciendoentrypoint.sh
que lea las variables de laENV
definición para poder usar el mismo enfoque que el ejemplo de MySQL, ¿verdad? Como complemento a su respuesta me encontré con este PR donde al parecer alguien está trabajando en algo similar a la propuesta que acaba de venir desde otro punto de vistaset -e
hace que todo el script se cierre cuando falla un comando, por lo que el script no puede fallar silenciosamente y arrancar mongo.&&
todas partes.docker-entrypoint-initdb.d
directorio lo hace extensible. Espero que se fusionenAquí otra solución más limpia usando
docker-compose
unjs
script.Este ejemplo asume que ambos archivos (docker-compose.yml y mongo-init.js) se encuentran en la misma carpeta.
docker-compose.yml
version: '3.7' services: mongodb: image: mongo:latest container_name: mongodb restart: always environment: MONGO_INITDB_ROOT_USERNAME: <admin-user> MONGO_INITDB_ROOT_PASSWORD: <admin-password> MONGO_INITDB_DATABASE: <database to create> ports: - 27017:27017 volumes: - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
mongo-init.js
db.createUser( { user: "<user for database which shall be created>", pwd: "<password of user>", roles: [ { role: "readWrite", db: "<database to create>" } ] } );
Luego, simplemente inicie el servicio ejecutando el siguiente comando docker-compose
Nota : El código de la carpeta docker-entrypoint-init.d solo se ejecuta si la base de datos nunca se ha inicializado antes.
fuente
volumes
entrada./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
vincula el archivo local./mongo-init.js
a la ruta del contenedor/docker-entrypoint-initdb.d/mongo-init.js
como de solo lecturaro
. Puede encontrar más detalles sobre cómo usar los volúmenes aquí: docs.docker.com/storage/volumesvolumes
opción y agregue la ruta absoluta almongo-init.js
archivo, por ejemploc:\docker\mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
.Aquí hay una solución funcional que crea un
admin-user
usuario con una contraseña, una base de datos adicional (test-database
) ytest-user
en esa base de datos.Dockerfile:
FROM mongo:4.0.3 ENV MONGO_INITDB_ROOT_USERNAME admin-user ENV MONGO_INITDB_ROOT_PASSWORD admin-password ENV MONGO_INITDB_DATABASE admin ADD mongo-init.js /docker-entrypoint-initdb.d/
mongo-init.js:
db.auth('admin-user', 'admin-password') db = db.getSiblingDB('test-database') db.createUser({ user: 'test-user', pwd: 'test-password', roles: [ { role: 'root', db: 'test-database', }, ], });
La parte complicada fue entender que los archivos * .js se ejecutaron sin autenticar. La solución autentica el script como
admin-user
en laadmin
base de datos.MONGO_INITDB_DATABASE admin
es esencial, de lo contrario, el script se ejecutaría contra la base de datostest
. Verifique el código fuente de docker-entrypoint.sh .fuente
La imagen de Mongo puede verse afectada por una
MONGO_INITDB_DATABASE
variable , pero no creará la base de datos. Esta variable determina la base de datos actual al ejecutar/docker-entrypoint-initdb.d/*
scripts . Como no puede usar variables de entorno en scripts ejecutados por Mongo, elegí un script de shell:docker-swarm.yml
:version: '3.1' secrets: mongo-root-passwd: file: mongo-root-passwd mongo-user-passwd: file: mongo-user-passwd services: mongo: image: mongo:3.2 environment: MONGO_INITDB_ROOT_USERNAME: $MONGO_ROOT_USER MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo-root-passwd MONGO_INITDB_USERNAME: $MONGO_USER MONGO_INITDB_PASSWORD_FILE: /run/secrets/mongo-user-passwd MONGO_INITDB_DATABASE: $MONGO_DB volumes: - ./init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh secrets: - mongo-root-passwd - mongo-user-passwd
init-mongo.sh
:mongo -- "$MONGO_INITDB_DATABASE" <<EOF var rootUser = '$MONGO_INITDB_ROOT_USERNAME'; var rootPassword = '$MONGO_INITDB_ROOT_PASSWORD'; var admin = db.getSiblingDB('admin'); admin.auth(rootUser, rootPassword); var user = '$MONGO_INITDB_USERNAME'; var passwd = '$(cat "$MONGO_INITDB_PASSWORD_FILE")'; db.createUser({user: user, pwd: passwd, roles: ["readWrite"]}); EOF
Alternativamente, puede almacenar
init-mongo.sh
en configs (docker config create
) y montarlo con:configs: init-mongo.sh: external: true ... services: mongo: ... configs: - source: init-mongo.sh target: /docker-entrypoint-initdb.d/init-mongo.sh
Y los secretos no se pueden almacenar en un archivo.
Un par de ideas al respecto.
fuente
$(cat "$MONGO_INITDB_ROOT_PASSWORD_FILE")
Debería reemplazarse por$MONGO_INITDB_ROOT_PASSWORD
estos días porque la imagen de Mongo ya maneja el secreto por nosotros. hub.docker.com/_/mongoEn caso de que alguien esté buscando cómo configurar MongoDB con autenticación usando
docker-compose
, aquí hay una configuración de muestra usando variables de entorno:version: "3.3" services: db: image: mongo environment: - MONGO_INITDB_ROOT_USERNAME=admin - MONGO_INITDB_ROOT_PASSWORD=<YOUR_PASSWORD> ports: - "27017:27017"
Cuando se ejecuta,
docker-compose up
su instancia de mongo se ejecuta automáticamente con la autenticación habilitada. Tendrá una base de datos de administrador con la contraseña proporcionada.fuente
mongo --username admin --password password --host localhost --port 27017
No puedo conectarme porque los registros muestran a los usuarios y la base de datos se ha creado correctamente. ERROR:$ mongo --username admin --password password --host localhost --port 27017 MongoDB shell version v3.4.10 connecting to: mongodb://localhost:27017/ MongoDB server version: 3.6.5 WARNING: shell and server versions do not match 2018-06-07T13:05:09.022+0000 E QUERY [thread1] Error: Authentication failed. : DB.prototype._authOrThrow@src/mongo/shell/db.js:1461:20 @(auth):6:1 @(auth):1:2 exception: login failed
mongo admin --username ADMIN --password PASSWORT
conectarte a tu instancia de mongo.mongodb://root:example@localhost/my-db?authSource=admin
Si está buscando eliminar nombres de usuario y contraseñas de su docker-compose.yml, puede usar Docker Secrets , así es como lo he abordado.
version: '3.6' services: db: image: mongo:3 container_name: mycontainer secrets: - MONGO_INITDB_ROOT_USERNAME - MONGO_INITDB_ROOT_PASSWORD environment: - MONGO_INITDB_ROOT_USERNAME_FILE=/var/run/secrets/MONGO_INITDB_ROOT_USERNAME - MONGO_INITDB_ROOT_PASSWORD_FILE=/var/run/secrets/MONGO_INITDB_ROOT_PASSWORD secrets: MONGO_INITDB_ROOT_USERNAME: file: secrets/${NODE_ENV}_mongo_root_username.txt MONGO_INITDB_ROOT_PASSWORD: file: secrets/${NODE_ENV}_mongo_root_password.txt
He usado la opción file: para mis secretos, sin embargo, también puedes usar external: y usar los secretos en un enjambre.
Los secretos están disponibles para cualquier script en el contenedor en / var / run / secrets
La documentación de Docker tiene esto que decir sobre el almacenamiento de datos confidenciales ...
https://docs.docker.com/engine/swarm/secrets/
Puede usar secretos para administrar los datos confidenciales que necesita un contenedor en tiempo de ejecución, pero no desea almacenarlos en la imagen o en el control de fuente, como:
Nombres de usuario y contraseñas Certificados y claves TLS Claves SSH Otros datos importantes como el nombre de una base de datos o un servidor interno Cadenas genéricas o contenido binario (hasta 500 kb de tamaño)
fuente
Dado este
.env
archivo:Y este
mongo-init.sh
archivo:mongo --eval "db.auth('$MONGO_INITDB_ROOT_USERNAME', '$MONGO_INITDB_ROOT_PASSWORD'); db = db.getSiblingDB('$DB_NAME'); db.createUser({ user: '$DB_USER', pwd: '$DB_PASSWORD', roles: [{ role: 'readWrite', db: '$DB_NAME' }] });"
Esto
docker-compose.yml
creará la base de datos de administrador y el usuario de administrador, se autenticará como el usuario de administrador, luego creará la base de datos real y agregará el usuario real:version: '3' services: # app: # build: . # env_file: .env # environment: # DB_HOST: 'mongodb://mongodb' mongodb: image: mongo:4 environment: MONGO_INITDB_ROOT_USERNAME: admin-user MONGO_INITDB_ROOT_PASSWORD: admin-password DB_NAME: $DB_NAME DB_USER: $DB_USER DB_PASSWORD: $DB_PASSWORD ports: - 27017:27017 volumes: - db-data:/data/db - ./mongo-init.sh:/docker-entrypoint-initdb.d/mongo-init.sh volumes: db-data:
fuente