How can I pass environment variables to mongo docker-entrypoint-initdb.d?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The MongoDB Docker image can run initialization scripts from /docker-entrypoint-initdb.d, but how those scripts receive configuration depends on the script type. Shell scripts can read container environment variables directly, while JavaScript init files need a wrapper if you want to inject values such as usernames, database names, or seed data options.
How docker-entrypoint-initdb.d Works
The official image executes files from /docker-entrypoint-initdb.d during first-time initialization, when the data directory is empty. That means these scripts are for bootstrap logic, not for code that should run every container start.
A typical Compose setup looks like this:
Those environment variables exist in the container process, so shell scripts can use them directly.
Use a Shell Script When You Need Environment Variables
A .sh file is the simplest way to consume custom variables.
Because the shell expands variables before launching mongosh, the values arrive in the executed commands naturally.
Why Plain .js Files Are Different
A .js file in /docker-entrypoint-initdb.d runs as JavaScript, not as a shell script. JavaScript does not automatically interpolate container environment variables like $APP_DB_NAME. If you write this inside a plain init file:
it will not work the way a shell script would. The JavaScript engine has no special awareness of shell environment variables.
That is why developers often think the variables are “missing” when the real problem is the script type.
A Reliable Pattern: Shell Wrapper Plus mongosh
If you prefer JavaScript logic, keep it inside a shell wrapper and pass values explicitly.
This keeps the environment-variable handling in the shell, where it belongs, while still letting you write database logic in JavaScript.
File Ordering and Idempotence
Scripts are processed in filename order. If one script creates a database and the next inserts seed data, name them accordingly, such as 01-users.sh and 02-seed.sh.
Also remember that these scripts run only on first initialization. If you change the script later but reuse the same persisted volume, Docker will not rerun it automatically. For local testing, you may need to remove the volume and start fresh.
Use that carefully, because -v removes persisted database data.
Keep Secrets Out of the Image
Do not bake credentials into your init scripts. Pass them through environment variables or secret-management tooling and keep the scripts generic. That makes the same initialization logic reusable across local development, CI, and staging.
Common Pitfalls
The biggest mistake is expecting plain .js init files to expand shell variables automatically. Another is forgetting that init scripts only run when the database directory is empty, which makes later changes appear ineffective. Developers also often confuse Mongo root credentials with application-user credentials and authenticate against the wrong database. Finally, when values contain special characters, careless shell quoting can break the generated commands.
Summary
- Shell init scripts can read container environment variables directly.
- Plain JavaScript init files do not automatically expand shell variables.
- Use a
.shwrapper when you need env-driven database setup. - Init scripts run only on first container initialization.
- Preserve quoting carefully so usernames, passwords, and database names are passed correctly.

