Skip to content

Commit da58c70

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

File tree

6 files changed

+307
-9
lines changed

6 files changed

+307
-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: 91 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,94 @@ 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+
if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
76+
rootAuthDatabase='admin'
77+
78+
"${mongo[@]}" "$rootAuthDatabase" <<-EOJS
79+
db.createUser({
80+
user: $(jq --arg 'user' "$MONGO_INITDB_ROOT_USERNAME" --null-input '$user'),
81+
pwd: $(jq --arg 'pwd' "$MONGO_INITDB_ROOT_PASSWORD" --null-input '$pwd'),
82+
roles: [ { role: 'root', db: $(jq --arg 'db' "$rootAuthDatabase" --null-input '$db') } ]
83+
})
84+
EOJS
85+
86+
mongo+=(
87+
--username="$MONGO_INITDB_ROOT_USERNAME"
88+
--password="$MONGO_INITDB_ROOT_PASSWORD"
89+
--authenticationDatabase="$rootAuthDatabase"
90+
)
91+
fi
92+
93+
export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}"
94+
95+
echo
96+
for f in /docker-entrypoint-initdb.d/*; do
97+
case "$f" in
98+
*.sh) echo "$0: running $f"; . "$f" ;;
99+
*.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;;
100+
*) echo "$0: ignoring $f" ;;
101+
esac
102+
echo
103+
done
104+
105+
"$@" --shutdown
106+
107+
echo
108+
echo 'MongoDB init process complete; ready for start up.'
109+
echo
110+
fi
111+
112+
unset MONGO_INITDB_ROOT_USERNAME
113+
unset MONGO_INITDB_ROOT_PASSWORD
114+
unset MONGO_INITDB_DATABASE
115+
fi
116+
26117
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: 101 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,104 @@ 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+
# TODO figure out why only MongoDB 3.2 seems to exit from "--fork" before it's actually listening
76+
# (adding "sleep 0.01" was sufficient on Tianon's local box, hence this tiny "retry up to one time")
77+
if ! "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then
78+
sleep 5
79+
if ! "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then
80+
echo >&2 'error: mongod does not appear to have started up quickly enough -- perhaps it had an error?'
81+
exit 1
82+
fi
83+
fi
84+
85+
if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then
86+
rootAuthDatabase='admin'
87+
88+
"${mongo[@]}" "$rootAuthDatabase" <<-EOJS
89+
db.createUser({
90+
user: $(jq --arg 'user' "$MONGO_INITDB_ROOT_USERNAME" --null-input '$user'),
91+
pwd: $(jq --arg 'pwd' "$MONGO_INITDB_ROOT_PASSWORD" --null-input '$pwd'),
92+
roles: [ { role: 'root', db: $(jq --arg 'db' "$rootAuthDatabase" --null-input '$db') } ]
93+
})
94+
EOJS
95+
96+
mongo+=(
97+
--username="$MONGO_INITDB_ROOT_USERNAME"
98+
--password="$MONGO_INITDB_ROOT_PASSWORD"
99+
--authenticationDatabase="$rootAuthDatabase"
100+
)
101+
fi
102+
103+
export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}"
104+
105+
echo
106+
for f in /docker-entrypoint-initdb.d/*; do
107+
case "$f" in
108+
*.sh) echo "$0: running $f"; . "$f" ;;
109+
*.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;;
110+
*) echo "$0: ignoring $f" ;;
111+
esac
112+
echo
113+
done
114+
115+
"$@" --shutdown
116+
117+
echo
118+
echo 'MongoDB init process complete; ready for start up.'
119+
echo
120+
fi
121+
122+
unset MONGO_INITDB_ROOT_USERNAME
123+
unset MONGO_INITDB_ROOT_PASSWORD
124+
unset MONGO_INITDB_DATABASE
125+
fi
126+
26127
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)