Ich arbeite mit Docker und habe einen Stack mit PHP, MySQL, Apache und Redis. Ich brauche MongoDB jetzt hinzufügen , damit ich die Überprüfung Dockerfile für die neueste Version und auch die docker-entrypoint.sh Datei aus dem MongoDB Dockerhub aber ich konnte nicht einen Weg , um das Einrichten eines Standard - DB, Admin - Benutzer / Passwort und möglicherweise Auth finden Methode für den Container aus einer docker-compose.yml
Datei.
In MySQL können Sie einige ENV-Variablen wie folgt einrichten:
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}
Dadurch werden die Datenbank und der Benutzer / das Kennwort als root
Kennwort eingerichtet.
Gibt es eine Möglichkeit, dies mit MongoDB zu erreichen? Hat jemand Erfahrung oder Problemumgehung?
mongodb
docker
docker-compose
ReynierPM
quelle
quelle
Antworten:
Das offizielle
mongo
Image hat eine PR zusammengeführt, um die Funktionalität zum Erstellen von Benutzern und Datenbanken beim Start einzuschließen.Die Datenbankinitialisierung wird ausgeführt, wenn das
/data/db
Verzeichnis nichts enthält .Admin User Setup
Die Umgebungsvariablen zur Steuerung des Benutzer-Setups "root" sind:
MONGO_INITDB_ROOT_USERNAME
MONGO_INITDB_ROOT_PASSWORD
Beispiel
Sie müssen / können nicht
--auth
in der Befehlszeile verwenden, da das Docker-Skript entrypoint.sh dies hinzufügt, wenn die Umgebungsvariablen vorhanden sind.Datenbankinitialisierung
Das Image enthält auch den
/docker-entrypoint-initdb.d/
Pfad zum Bereitstellen von benutzerdefinierten.js
oder.sh
Setup-Skripten, die bei der Datenbankinitialisierung einmal ausgeführt werden..js
Skripte werdentest
standardmäßig oderMONGO_INITDB_DATABASE
in der Umgebung definiert ausgeführt.oder
Eine einfache Javascript- Datei für die Mongo-Shell zur Initialisierung , die das Einrichten der
container
Sammlung mit Daten, die Protokollierung und das Beenden mit einem Fehler (zur Ergebnisprüfung) demonstriert .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) }
quelle
set -e
heißt,entrypoint.sh
Variablen aus derENV
Definition zu lesen, damit ich den gleichen Ansatz wie im Beispiel von MySQL verwenden kann. Als Ergänzung zu Ihrer Antwort habe ich diese PR gefunden, in der anscheinend jemand in etwas ähnlichem wie Ihrem Vorschlag arbeitet, nur aus einem anderen Blickwinkelset -e
bewirkt, dass das gesamte Skript beendet wird, wenn ein Befehl fehlschlägt, sodass das Skript nicht stillschweigend fehlschlagen und mongo starten kann.&&
überall verwendet werden.docker-entrypoint-initdb.d
Verzeichnis macht es erweiterbar. Ich hoffe, dass das zusammengeführt wirdHier eine weitere sauberere Lösung mit
docker-compose
und einemjs
Skript.In diesem Beispiel wird davon ausgegangen, dass sich beide Dateien (docker-compose.yml und mongo-init.js) im selben Ordner befinden.
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>" } ] } );
Starten Sie dann einfach den Dienst, indem Sie den folgenden Docker-Compose-Befehl ausführen
Hinweis : Der Code im Ordner docker-entrypoint-init.d wird nur ausgeführt, wenn die Datenbank noch nie zuvor initialisiert wurde.
quelle
volumes
Eintrag./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
verknüpft die lokale Datei schreibgeschützt./mongo-init.js
mit dem Containerpfad . Weitere Informationen zur Verwendung von Volumes finden Sie hier: docs.docker.com/storage/volumes/docker-entrypoint-initdb.d/mongo-init.js
ro
volumes
Option an und fügen Sie beispielsweise den absoluten Pfad zurmongo-init.js
Datei hinzuc:\docker\mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
.Hier ist eine funktionierende Lösung, die
admin-user
Benutzer mit einem Kennwort, einer zusätzlichen Datenbank (test-database
) undtest-user
in dieser Datenbank erstellt.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', }, ], });
Der schwierige Teil war zu verstehen, dass * .js-Dateien nicht authentifiziert ausgeführt wurden. Die Lösung authentifiziert das Skript als
admin-user
in deradmin
Datenbank.MONGO_INITDB_DATABASE admin
ist wichtig, sonst würde das Skript gegen dietest
Datenbank ausgeführt. Überprüfen Sie den Quellcode von docker-entrypoint.sh .quelle
Das Mongo-Bild kann von
MONGO_INITDB_DATABASE
Variablen beeinflusst werden, die Datenbank wird jedoch nicht erstellt. Diese Variable bestimmt die aktuelle Datenbank beim Ausführen von/docker-entrypoint-initdb.d/*
Skripten . Da Sie in von Mongo ausgeführten Skripten keine Umgebungsvariablen verwenden können, habe ich mich für ein Shell-Skript entschieden: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
Alternativ können Sie
init-mongo.sh
in configs (docker config create
) speichern und es einbinden mit:configs: init-mongo.sh: external: true ... services: mongo: ... configs: - source: init-mongo.sh target: /docker-entrypoint-initdb.d/init-mongo.sh
Und Geheimnisse können nicht in einer Datei gespeichert werden.
Ein paar von Logen über die Angelegenheit.
quelle
$(cat "$MONGO_INITDB_ROOT_PASSWORD_FILE")
sollte durch$MONGO_INITDB_ROOT_PASSWORD
diese Tage ersetzt werden, da das Mongo-Bild bereits das Geheimnis für uns behandelt. hub.docker.com/_/mongoFür den Fall, dass jemand nach einer Konfiguration von MongoDB mit Authentifizierung mithilfe von sucht
docker-compose
, finden Sie hier eine Beispielkonfiguration mit Umgebungsvariablen:version: "3.3" services: db: image: mongo environment: - MONGO_INITDB_ROOT_USERNAME=admin - MONGO_INITDB_ROOT_PASSWORD=<YOUR_PASSWORD> ports: - "27017:27017"
Beim Ausführen wird
docker-compose up
Ihre Mongo-Instanz automatisch mit aktivierter Authentifizierung ausgeführt. Sie haben eine Admin-Datenbank mit dem angegebenen Passwort.quelle
mongo --username admin --password password --host localhost --port 27017
Ich kann keine Verbindung herstellen, da die Protokolle die Benutzer anzeigen und die Datenbank erfolgreich erstellt wurde. FEHLER:$ 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
Verbindung zu Ihrer Mongo-Instanz herstellen.mongodb://root:example@localhost/my-db?authSource=admin
Wenn Sie Benutzernamen und Passwörter aus Ihrer docker-compose.yml entfernen möchten, können Sie Docker Secrets verwenden . So habe ich es angegangen.
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
Ich habe die Option file: für meine Geheimnisse verwendet, Sie können jedoch auch external: verwenden und die Geheimnisse in einem Schwarm verwenden.
Die Geheimnisse stehen jedem Skript im Container unter / var / run / Secrets zur Verfügung
In der Docker-Dokumentation wird Folgendes zum Speichern vertraulicher Daten angegeben ...
https://docs.docker.com/engine/swarm/secrets/
Sie können Geheimnisse verwenden, um vertrauliche Daten zu verwalten, die ein Container zur Laufzeit benötigt, die Sie jedoch nicht im Image oder in der Quellcodeverwaltung speichern möchten, z.
Benutzernamen und Passwörter TLS-Zertifikate und -Schlüssel SSH-Schlüssel Andere wichtige Daten wie der Name einer Datenbank oder eines internen Servers Generische Zeichenfolgen oder binäre Inhalte (bis zu 500 KB groß)
quelle
Angesichts dieser
.env
Datei:Und diese
mongo-init.sh
Datei: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' }] });"
Dadurch
docker-compose.yml
werden die Administratordatenbank und der Administratorbenutzer erstellt, als Administratorbenutzer authentifiziert, dann die reale Datenbank erstellt und der reale Benutzer hinzugefügt: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:
quelle