Skip to content

Commit 27f2722

Browse files
committed
Add "docker-entrypoint-initdb.d" behavior which mimics PostgreSQL, including (optional) automated "root" user creation
1 parent 9067caa commit 27f2722

File tree

6 files changed

+326
-9
lines changed

6 files changed

+326
-9
lines changed

3.0/Dockerfile

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
FROM debian:wheezy
1+
FROM debian:wheezy-slim
22

33
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
44
RUN groupadd -r mongodb && useradd -r -g mongodb mongodb
55

6+
# add "wheezy-backports" for "jq"
7+
RUN echo 'deb http://deb.debian.org/debian wheezy-backports main' > /etc/apt/sources.list.d/backports.list
8+
69
RUN apt-get update \
710
&& apt-get install -y --no-install-recommends \
11+
jq \
812
numactl \
913
&& rm -rf /var/lib/apt/lists/*
1014

@@ -22,6 +26,8 @@ RUN set -x \
2226
&& gosu nobody true \
2327
&& apt-get purge -y --auto-remove ca-certificates wget
2428

29+
RUN mkdir /docker-entrypoint-initdb.d
30+
2531
ENV GPG_KEYS \
2632
# gpg: key 7F0CEB10: public key "Richard Kreuter <[email protected]>" imported
2733
492EAFE8CD016A07919F1D2B9ECBEC467F0CEB10
@@ -56,8 +62,9 @@ RUN mkdir -p /data/db /data/configdb \
5662
&& chown -R mongodb:mongodb /data/db /data/configdb
5763
VOLUME /data/db /data/configdb
5864

59-
COPY docker-entrypoint.sh /entrypoint.sh
60-
ENTRYPOINT ["/entrypoint.sh"]
65+
COPY docker-entrypoint.sh /usr/local/bin/
66+
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
67+
ENTRYPOINT ["docker-entrypoint.sh"]
6168

6269
EXPOSE 27017
6370
CMD ["mongod"]

3.0/docker-entrypoint.sh

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ if [[ "$1" == mongo* ]] && [ "$(id -u)" = '0' ]; then
1111
if [ "$1" = 'mongod' ]; then
1212
chown -R mongodb /data/configdb /data/db
1313
fi
14+
chown --dereference mongodb /dev/stdout /dev/stderr
1415
exec gosu mongodb "$BASH_SOURCE" "$@"
1516
fi
1617

@@ -23,4 +24,102 @@ if [[ "$1" == mongo* ]]; then
2324
fi
2425
fi
2526

27+
# usage: file_env VAR [DEFAULT]
28+
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
29+
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
30+
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
31+
file_env() {
32+
local var="$1"
33+
local fileVar="${var}_FILE"
34+
local def="${2:-}"
35+
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
36+
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
37+
exit 1
38+
fi
39+
local val="$def"
40+
if [ "${!var:-}" ]; then
41+
val="${!var}"
42+
elif [ "${!fileVar:-}" ]; then
43+
val="$(< "${!fileVar}")"
44+
fi
45+
export "$var"="$val"
46+
unset "$fileVar"
47+
}
48+
49+
if [ "$1" = 'mongod' ]; then
50+
file_env 'MONGO_INITDB_ROOT_USERNAME'
51+
file_env 'MONGO_INITDB_ROOT_PASSWORD'
52+
if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
53+
set -- "$@" --auth
54+
fi
55+
56+
# check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts)
57+
definitelyAlreadyInitialized=
58+
for path in \
59+
/data/db/WiredTiger \
60+
/data/db/journal \
61+
/data/db/local.0 \
62+
/data/db/storage.bson \
63+
; do
64+
if [ -e "$path" ]; then
65+
definitelyAlreadyInitialized="$path"
66+
break
67+
fi
68+
done
69+
70+
if [ -z "$definitelyAlreadyInitialized" ]; then
71+
"$@" --fork --bind_ip 127.0.0.1 --logpath "/proc/$$/fd/1"
72+
73+
mongo=( mongo --quiet )
74+
75+
# check to see that "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, etc)
76+
if ! "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then
77+
echo >&2
78+
echo >&2 'error: mongod does not appear to have started up -- perhaps it had an error?'
79+
echo >&2
80+
exit 1
81+
fi
82+
83+
if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
84+
rootAuthDatabase='admin'
85+
86+
"${mongo[@]}" "$rootAuthDatabase" <<-EOJS
87+
db.createUser({
88+
user: $(jq --arg 'user' "$MONGO_INITDB_ROOT_USERNAME" --null-input '$user'),
89+
pwd: $(jq --arg 'pwd' "$MONGO_INITDB_ROOT_PASSWORD" --null-input '$pwd'),
90+
roles: [ { role: 'root', db: $(jq --arg 'db' "$rootAuthDatabase" --null-input '$db') } ]
91+
})
92+
EOJS
93+
94+
mongo+=(
95+
--username="$MONGO_INITDB_ROOT_USERNAME"
96+
--password="$MONGO_INITDB_ROOT_PASSWORD"
97+
--authenticationDatabase="$rootAuthDatabase"
98+
)
99+
fi
100+
101+
export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}"
102+
103+
echo
104+
for f in /docker-entrypoint-initdb.d/*; do
105+
case "$f" in
106+
*.sh) echo "$0: running $f"; . "$f" ;;
107+
*.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;;
108+
*) echo "$0: ignoring $f" ;;
109+
esac
110+
echo
111+
done
112+
113+
"$@" --shutdown
114+
115+
echo
116+
echo 'MongoDB init process complete; ready for start up.'
117+
echo
118+
fi
119+
120+
unset MONGO_INITDB_ROOT_USERNAME
121+
unset MONGO_INITDB_ROOT_PASSWORD
122+
unset MONGO_INITDB_DATABASE
123+
fi
124+
26125
exec "$@"

3.2/Dockerfile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
FROM debian:jessie
1+
FROM debian:jessie-slim
22

33
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
44
RUN groupadd -r mongodb && useradd -r -g mongodb mongodb
55

66
RUN apt-get update \
77
&& apt-get install -y --no-install-recommends \
8+
jq \
89
numactl \
910
&& rm -rf /var/lib/apt/lists/*
1011

@@ -22,6 +23,8 @@ RUN set -x \
2223
&& gosu nobody true \
2324
&& apt-get purge -y --auto-remove ca-certificates wget
2425

26+
RUN mkdir /docker-entrypoint-initdb.d
27+
2528
ENV GPG_KEYS \
2629
# pub 4096R/AAB2461C 2014-02-25 [expires: 2016-02-25]
2730
# Key fingerprint = DFFA 3DCF 326E 302C 4787 673A 01C4 E7FA AAB2 461C
@@ -62,8 +65,9 @@ RUN mkdir -p /data/db /data/configdb \
6265
&& chown -R mongodb:mongodb /data/db /data/configdb
6366
VOLUME /data/db /data/configdb
6467

65-
COPY docker-entrypoint.sh /entrypoint.sh
66-
ENTRYPOINT ["/entrypoint.sh"]
68+
COPY docker-entrypoint.sh /usr/local/bin/
69+
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
70+
ENTRYPOINT ["docker-entrypoint.sh"]
6771

6872
EXPOSE 27017
6973
CMD ["mongod"]

3.2/docker-entrypoint.sh

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ if [[ "$1" == mongo* ]] && [ "$(id -u)" = '0' ]; then
1111
if [ "$1" = 'mongod' ]; then
1212
chown -R mongodb /data/configdb /data/db
1313
fi
14+
chown --dereference mongodb /dev/stdout /dev/stderr
1415
exec gosu mongodb "$BASH_SOURCE" "$@"
1516
fi
1617

@@ -23,4 +24,107 @@ if [[ "$1" == mongo* ]]; then
2324
fi
2425
fi
2526

27+
# usage: file_env VAR [DEFAULT]
28+
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
29+
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
30+
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
31+
file_env() {
32+
local var="$1"
33+
local fileVar="${var}_FILE"
34+
local def="${2:-}"
35+
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
36+
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
37+
exit 1
38+
fi
39+
local val="$def"
40+
if [ "${!var:-}" ]; then
41+
val="${!var}"
42+
elif [ "${!fileVar:-}" ]; then
43+
val="$(< "${!fileVar}")"
44+
fi
45+
export "$var"="$val"
46+
unset "$fileVar"
47+
}
48+
49+
if [ "$1" = 'mongod' ]; then
50+
file_env 'MONGO_INITDB_ROOT_USERNAME'
51+
file_env 'MONGO_INITDB_ROOT_PASSWORD'
52+
if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
53+
set -- "$@" --auth
54+
fi
55+
56+
# check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts)
57+
definitelyAlreadyInitialized=
58+
for path in \
59+
/data/db/WiredTiger \
60+
/data/db/journal \
61+
/data/db/local.0 \
62+
/data/db/storage.bson \
63+
; do
64+
if [ -e "$path" ]; then
65+
definitelyAlreadyInitialized="$path"
66+
break
67+
fi
68+
done
69+
70+
if [ -z "$definitelyAlreadyInitialized" ]; then
71+
"$@" --fork --bind_ip 127.0.0.1 --logpath "/proc/$$/fd/1"
72+
73+
mongo=( mongo --quiet )
74+
75+
# check to see that "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, etc)
76+
if ! "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then
77+
# TODO figure out why only MongoDB 3.2 seems to exit from "--fork" before it's actually listening
78+
# (adding "sleep 0.01" was sufficient on Tianon's local box, hence this tiny "retry up to one time")
79+
sleep 5
80+
fi
81+
if ! "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then
82+
echo >&2
83+
echo >&2 'error: mongod does not appear to have started up -- perhaps it had an error?'
84+
echo >&2
85+
exit 1
86+
fi
87+
88+
if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
89+
rootAuthDatabase='admin'
90+
91+
"${mongo[@]}" "$rootAuthDatabase" <<-EOJS
92+
db.createUser({
93+
user: $(jq --arg 'user' "$MONGO_INITDB_ROOT_USERNAME" --null-input '$user'),
94+
pwd: $(jq --arg 'pwd' "$MONGO_INITDB_ROOT_PASSWORD" --null-input '$pwd'),
95+
roles: [ { role: 'root', db: $(jq --arg 'db' "$rootAuthDatabase" --null-input '$db') } ]
96+
})
97+
EOJS
98+
99+
mongo+=(
100+
--username="$MONGO_INITDB_ROOT_USERNAME"
101+
--password="$MONGO_INITDB_ROOT_PASSWORD"
102+
--authenticationDatabase="$rootAuthDatabase"
103+
)
104+
fi
105+
106+
export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}"
107+
108+
echo
109+
for f in /docker-entrypoint-initdb.d/*; do
110+
case "$f" in
111+
*.sh) echo "$0: running $f"; . "$f" ;;
112+
*.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;;
113+
*) echo "$0: ignoring $f" ;;
114+
esac
115+
echo
116+
done
117+
118+
"$@" --shutdown
119+
120+
echo
121+
echo 'MongoDB init process complete; ready for start up.'
122+
echo
123+
fi
124+
125+
unset MONGO_INITDB_ROOT_USERNAME
126+
unset MONGO_INITDB_ROOT_PASSWORD
127+
unset MONGO_INITDB_DATABASE
128+
fi
129+
26130
exec "$@"

3.4/Dockerfile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
FROM debian:jessie
1+
FROM debian:jessie-slim
22

33
# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
44
RUN groupadd -r mongodb && useradd -r -g mongodb mongodb
55

66
RUN apt-get update \
77
&& apt-get install -y --no-install-recommends \
8+
jq \
89
numactl \
910
&& rm -rf /var/lib/apt/lists/*
1011

@@ -22,6 +23,8 @@ RUN set -x \
2223
&& gosu nobody true \
2324
&& apt-get purge -y --auto-remove ca-certificates wget
2425

26+
RUN mkdir /docker-entrypoint-initdb.d
27+
2528
ENV GPG_KEYS \
2629
# pub 4096R/A15703C6 2016-01-11 [expires: 2018-01-10]
2730
# Key fingerprint = 0C49 F373 0359 A145 1858 5931 BC71 1F9B A157 03C6
@@ -58,8 +61,9 @@ RUN mkdir -p /data/db /data/configdb \
5861
&& chown -R mongodb:mongodb /data/db /data/configdb
5962
VOLUME /data/db /data/configdb
6063

61-
COPY docker-entrypoint.sh /entrypoint.sh
62-
ENTRYPOINT ["/entrypoint.sh"]
64+
COPY docker-entrypoint.sh /usr/local/bin/
65+
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
66+
ENTRYPOINT ["docker-entrypoint.sh"]
6367

6468
EXPOSE 27017
6569
CMD ["mongod"]

0 commit comments

Comments
 (0)