I have a docker-compose that looks like this:
stock-trading-system-db:
container_name: stock-trading-system-db
image: mongo
restart: always
ports:
- "27017:27017"
environment:
- MONGO_INITDB_DATABASE=stock-trading-system-db
volumes:
- ./mongo-seed/import.js:/docker-entrypoint-initdb.d/import.js
- ./mongo-seed/mongod.conf:/etc/mongod.conf
- ./mongo/data:/data/db
- ./mongo-seed/MOCK_DATA.csv:/mongo-seed/MOCK_DATA.csv
and import.js
looks like this:
let exec = require('child_process').exec
let command1 = 'mongod --config /etc/mongod.conf'
let command2 = 'mongo --eval "rs.initiate();"'
let command3 = 'mongoimport --host=mongo1 --db=stock-trading-system-db --collection=stocks --type=csv --headerline --file=/mongo-seed/MOCK_DATA.csv'
exec(command1, (err, stdout, stderr) => {
// check for errors or if it was succesfuly
if(!err){
exec(command2, (err, stdout, stderr) => {
// check for errors or if it was succesfuly
if(!err){
exec(command3, (err, stdout, stderr) => {
// check for errors or if it was succesfuly
if(!err){
console.log('MongoDB seed was succesful');
}
})
}
})
}
})
But it doesn't seem like import.js
even gets recognised by the container.
The mongo docs say the following:
This variable allows you to specify the name of a database to be used for creation scripts in /docker-entrypoint-initdb.d/*.js (see Initializing a fresh instance below). MongoDB is fundamentally designed for "create on first use", so if you do not insert data with your JavaScript files, then no database is created.
This is in relation to the MONGO_INITDB_DATABASE
variable in the docker-compose file, which i have included.
Where am i going wrong?
p.s. This is all to try and get a single node replica set working in a mongo container so that I can use change streams in my node app, so if you know an easier way to do this whilst also importing a csv file into the DB then please mention it :)
CodePudding user response:
First, you shouldn't be trying to start mongod
in your init script;
the image already does this for you. When you run your first command:
mongod --config /etc/mongod.conf
That's it. That command doesn't exit, and nothing progresses beyond that point, so your additional commands will not execute nor will the normal container startup process complete.
So don't do that.
Next, if you want to run rs.initiate()
(or any other javascript
command) as part of the startup process, you don't need to wrap it in
a call to mongo --eval
. Just drop in a .js
file that contains:
rs.initiate()
And if you're just going to run a shell command, it's probably easiest just to drop that in a .sh
file.
I would replace your import.js
script with two seperate files. In rs-initiate.js
, I would have the call to rs.initiate()
, as above, and in import.sh
I would have your call to mongoimport
...
#!/bin/sh
mongoimport \
--db=stock-trading-system-db \
--collection=stocks \
--type=csv \
--headerline \
--file=/mongo-seed/MOCK_DATA.csv
...so that the docker-compose.yaml
would look like:
version: "3"
services:
mongo:
image: docker.io/mongo:latest
ports:
- "27017:27017"
environment:
- MONGO_INITDB_DATABASE=stock-trading-system-db
volumes:
- ./mongo-seed/import.sh:/docker-entrypoint-initdb.d/import.sh
- ./mongo-seed/rs-initiate.js:/docker-entrypoint-initdb.d/rs-initiate.js
- ./mongo-seed/MOCK_DATA.csv:/mongo-seed/MOCK_DATA.csv
- ./mongo-seed/mongod.conf:/etc/mongod.conf
- mongo_data:/data/db
volumes:
mongo_data:
I'm using a named volume for the mongo data directory here, rather than a bind mount, but that's not necessary; everything will work fine with the bind mount as long as you have permissions configured correctly.
CodePudding user response:
When using bind mounts, the file or directory is referenced by its absolute path on the host machine (see Docker docs).
So you should rather use:
volumes:
- ${PWD}/mongo-seed/import.js:/docker-entrypoint-initdb.d/import.js
- ...