可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am working with Docker and I have a stack with PHP, MySQL, Apache and Redis. I need to add MongoDB now so I was checking the Dockerfile for the latest version and also the docker-entrypoint.sh file from the MongoDB Dockerhub but I couldn't find a way to setup a default DB, admin user/password and possibly auth method for the container from a docker-compose.yml
file.
In MySQL you can setup some ENV variables as for example:
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}
And this will setup the DB and the user/password as the root
password.
Is there any way to achieve the same with MongoDB? Anyone has some experience or workaround?
回答1:
The official mongo
image has merged a PR to include the functionality to create users and databases at startup.
The database initialisation will run when there is nothing populated in the /data/db
directory.
Admin User Setup
The environment variables to control "root" user setup are
MONGO_INITDB_ROOT_USERNAME
MONGO_INITDB_ROOT_PASSWORD
Example
docker run -d \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=password \
mongod
You don't need to/can't use --auth
on the command line as the docker entrypoint.sh script adds this in when the environment variables exist.
Other Custom Initialisation
The image also provides the /docker-entrypoint-initdb.d/
path to deploy custom .js
or .sh
setup scripts that will be run once on database initialisation. .js
scripts will be run against test
by default or MONGO_INITDB_DATABASE
if defined in the environment.
COPY mysetup.sh /docker-entrypoint-initdb.d/
or
COPY mysetup.js /docker-entrypoint-initdb.d/
A simple initialisation javascript file that demonstrates logging and how to exit with an error (for result checking).
let error = true
let res = [
db.container.drop(),
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' }),
]
printjson(res)
if (error) {
print('Error, exiting')
quit(1)
}
回答2:
In case someone is looking for how to configure MongoDB with authentication using docker-compose
, here is a sample configuration using environment variables:
version: "3.3"
services:
db:
image: mongo
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=<YOUR_PASSWORD>
ports:
- "27017:27017"
When running docker-compose up
your mongo instance is run automatically with auth enabled. You will have a admin database with the given password.
回答3:
Here's a working solution that creates admin-user
user with a password, additional database (test-db
), and test-user
in that database.
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: 'admin',
},
],
});
The tricky part was to understand that *.js files were run unauthenticated.
The solution authenticates the script as the admin-user
in the admin
database. MONGO_INITDB_DATABASE admin
is essential, otherwise the script would be executed against the test
db. Check the source code of docker-entrypoint.sh.
回答4:
Mongo image can be affected by MONGO_INITDB_DATABASE
variable, but it won't create the database. This variable determines current database when running /docker-entrypoint-initdb.d/*
scripts. Since you can't use environment variables in scripts executed by Mongo, I went with a shell script:
docker-cloud.yml
:
version: '3.1'
secrets:
mongo-passwd:
file: mongo-passwd
services:
mongo:
image: mongo:3.2
environment:
MONGO_DB: ${MONGO_DB}
MONGO_INITDB_ROOT_USERNAME: ${MONGO_USER}
MONGO_INITDB_ROOT_PASSWORD_FILE: /run/secrets/mongo-passwd
volumes:
- ./init-mongo.sh:/docker-entrypoint-initdb.d/init-mongo.sh
secrets:
- mongo-passwd
init-mongo.sh
:
mongo -- "$MONGO_DB" <<EOF
var user = '$MONGO_INITDB_ROOT_USERNAME';
var passwd = '$MONGO_INITDB_ROOT_PASSWORD';
var admin = db.getSiblingDB('admin');
admin.auth(user, passwd);
db.createUser({user: user, pwd: passwd, roles: ["readWrite"]});
EOF
回答5:
Here another cleaner solution by using docker-compose
and a js
script.
This example assumes that both files (docker-compose.yml and mongo-init.js) lay in the same folder.
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>"
}
]
}
);
Then simply start the service by running the following docker-compose command
docker-compose up --build -d mongodb
回答6:
If you are looking to remove usernames and passwords from your docker-compose.yml you can use Docker Secrets, here is how I have approached it.
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
I have use the file: option for my secrets however, you can also use external: and use the secrets in a swarm.
The secrets are available to any script in the container at /var/run/secrets
The Docker documentation has this to say about storing sensitive data...
https://docs.docker.com/engine/swarm/secrets/
You can use secrets to manage any sensitive data which a container needs at runtime but you don’t want to store in the image or in source control, such as:
Usernames and passwords
TLS certificates and keys
SSH keys
Other important data such as the name of a database or internal server
Generic strings or binary content (up to 500 kb in size)