From 7354afb4e7e8623ffb0eea1ce7f1adda0bbaa2e5 Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Mon, 12 Jan 2026 09:31:27 -0700 Subject: [PATCH 01/10] Add a community build for each version of mongo 4-8 --- .../Dockerfile | 79 +++ percona-server-mongodb-4.4-community/LICENSE | 7 + .../mongodb.repo | 6 + .../ps-entry.sh | 462 ++++++++++++++++++ .../Dockerfile | 79 +++ percona-server-mongodb-5.0-community/LICENSE | 7 + .../mongodb.repo | 6 + .../ps-entry.sh | 462 ++++++++++++++++++ .../Dockerfile | 79 +++ percona-server-mongodb-6.0-community/LICENSE | 7 + .../mongodb.repo | 6 + .../ps-entry.sh | 462 ++++++++++++++++++ .../Dockerfile | 79 +++ percona-server-mongodb-7.0-community/LICENSE | 7 + .../mongodb.repo | 6 + .../ps-entry.sh | 462 ++++++++++++++++++ .../Dockerfile | 79 +++ percona-server-mongodb-8.0-community/LICENSE | 7 + .../mongodb.repo | 6 + .../ps-entry.sh | 462 ++++++++++++++++++ 20 files changed, 2770 insertions(+) create mode 100644 percona-server-mongodb-4.4-community/Dockerfile create mode 100644 percona-server-mongodb-4.4-community/LICENSE create mode 100644 percona-server-mongodb-4.4-community/mongodb.repo create mode 100644 percona-server-mongodb-4.4-community/ps-entry.sh create mode 100644 percona-server-mongodb-5.0-community/Dockerfile create mode 100644 percona-server-mongodb-5.0-community/LICENSE create mode 100644 percona-server-mongodb-5.0-community/mongodb.repo create mode 100644 percona-server-mongodb-5.0-community/ps-entry.sh create mode 100644 percona-server-mongodb-6.0-community/Dockerfile create mode 100644 percona-server-mongodb-6.0-community/LICENSE create mode 100644 percona-server-mongodb-6.0-community/mongodb.repo create mode 100644 percona-server-mongodb-6.0-community/ps-entry.sh create mode 100644 percona-server-mongodb-7.0-community/Dockerfile create mode 100644 percona-server-mongodb-7.0-community/LICENSE create mode 100644 percona-server-mongodb-7.0-community/mongodb.repo create mode 100644 percona-server-mongodb-7.0-community/ps-entry.sh create mode 100644 percona-server-mongodb-8.0-community/Dockerfile create mode 100644 percona-server-mongodb-8.0-community/LICENSE create mode 100644 percona-server-mongodb-8.0-community/mongodb.repo create mode 100644 percona-server-mongodb-8.0-community/ps-entry.sh diff --git a/percona-server-mongodb-4.4-community/Dockerfile b/percona-server-mongodb-4.4-community/Dockerfile new file mode 100644 index 00000000..0c1b268c --- /dev/null +++ b/percona-server-mongodb-4.4-community/Dockerfile @@ -0,0 +1,79 @@ +FROM redhat/ubi9-minimal + +LABEL name="MongoDB Community Edition" \ + release="4.4" \ + vendor="MongoDB Inc." \ + summary="MongoDB Community Edition with Percona operator compatibility" \ + description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ + maintainer="Percona Development " +LABEL org.opencontainers.image.authors="info@percona.com" + +ENV PSMDB_VERSION 4.4.29 +ENV OS_VER el9 + +# Do not report during Docker image creation. +ARG PERCONA_TELEMETRY_DISABLE=1 + +COPY mongodb.repo /etc/yum.repos.d/mongodb.repo + +RUN set -ex; \ + microdnf -y update glibc; \ + microdnf -y update libgcrypt; \ + microdnf -y install \ + mongodb-org-${PSMDB_VERSION} \ + mongodb-org-database-${PSMDB_VERSION} \ + mongodb-org-server-${PSMDB_VERSION} \ + mongodb-mongosh \ + mongodb-org-mongos-${PSMDB_VERSION} \ + mongodb-org-tools-${PSMDB_VERSION} \ + numactl \ + numactl-libs \ + procps-ng \ + jq \ + tar \ + oniguruma \ + cyrus-sasl-gssapi \ + cyrus-sasl-plain \ + policycoreutils; \ + microdnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ + chown -R 1001:0 /data/db + +# the numeric UID is needed for OpenShift +RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ + -c "Default Application User" mongodb; \ + chmod g+rwx /var/log/mongo; \ + chown :0 /var/log/mongo + +COPY LICENSE /licenses/LICENSE.Dockerfile +RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ + echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community + +ENV GOSU_VERSION=1.11 +RUN set -eux; \ + curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ + curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ + rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ + \ + chmod +x /usr/bin/gosu; \ + curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE + +VOLUME ["/data/db"] + +RUN set -ex; \ + curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ + echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - + +COPY ps-entry.sh /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] + +EXPOSE 27017 + +USER 1001 + +CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-4.4-community/LICENSE b/percona-server-mongodb-4.4-community/LICENSE new file mode 100644 index 00000000..0ae7afb4 --- /dev/null +++ b/percona-server-mongodb-4.4-community/LICENSE @@ -0,0 +1,7 @@ +MongoDB Community Edition License + +This software is licensed under the Server Side Public License (SSPL) v1. +For more information, see: https://www.mongodb.com/licensing/server-side-public-license + +This Docker image contains MongoDB Community Edition binaries and is configured +for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-4.4-community/mongodb.repo b/percona-server-mongodb-4.4-community/mongodb.repo new file mode 100644 index 00000000..7b2f9361 --- /dev/null +++ b/percona-server-mongodb-4.4-community/mongodb.repo @@ -0,0 +1,6 @@ +[mongodb-org-4.4] +name=MongoDB Repository +baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/4.4/x86_64/ +gpgcheck=1 +enabled=1 +gpgkey=https://pgp.mongodb.com/server-4.4.asc \ No newline at end of file diff --git a/percona-server-mongodb-4.4-community/ps-entry.sh b/percona-server-mongodb-4.4-community/ps-entry.sh new file mode 100644 index 00000000..89cb67af --- /dev/null +++ b/percona-server-mongodb-4.4-community/ps-entry.sh @@ -0,0 +1,462 @@ +#!/bin/bash +set -Eeuo pipefail + +if [ "${1:0:1}" = '-' ]; then + set -- mongod "$@" +fi + +originalArgOne="$1" + +# allow the container to be started with `--user` +# all mongo* commands should be dropped to the correct user +if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then + if [ "$originalArgOne" = 'mongod' ]; then + if [ -d "/data/configdb" ]; then + find /data/configdb \! -user mongodb -exec chown mongodb '{}' + + fi + if [ -d "/data/db" ]; then + find /data/db \! -user mongodb -exec chown mongodb '{}' + + fi + fi + + # make sure we can write to stdout and stderr as "mongodb" + # (for our "initdb" code later; see "--logpath" below) + chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : + # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 + + exec gosu mongodb:1001 "$BASH_SOURCE" "$@" +fi + +# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. +# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux +if [[ "$originalArgOne" == mongo* ]]; then + numa='numactl --interleave=all' + if $numa true &> /dev/null; then + set -- $numa "$@" + fi +fi + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) +_mongod_hack_have_arg() { + local checkArg="$1"; shift + local arg + for arg; do + case "$arg" in + "$checkArg"|"$checkArg"=*) + return 0 + ;; + esac + done + return 1 +} +# _mongod_hack_get_arg_val '--some-arg' "$@" +_mongod_hack_get_arg_val() { + local checkArg="$1"; shift + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$checkArg") + echo "$1" + return 0 + ;; + "$checkArg"=*) + echo "${arg#$checkArg=}" + return 0 + ;; + esac + done + return 1 +} +declare -a mongodHackedArgs +# _mongod_hack_ensure_arg '--some-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg() { + local ensureArg="$1"; shift + mongodHackedArgs=( "$@" ) + if ! _mongod_hack_have_arg "$ensureArg" "$@"; then + mongodHackedArgs+=( "$ensureArg" ) + fi +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$ensureNoArg" ]; then + continue + fi + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg_val() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$ensureNoArg") + shift # also skip the value + continue + ;; + "$ensureNoArg"=*) + # value is already included + continue + ;; + esac + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg_val() { + local ensureArg="$1"; shift + local ensureVal="$1"; shift + _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" + mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg_save_val() { + local oldArg="$1"; shift + local newArg="$1"; shift + if ! _mongod_hack_have_arg "$oldArg" "$@"; then + return 0 + fi + local val="" + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$oldArg" ]; then + val="$1"; shift + continue + elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then + val=${BASH_REMATCH[1]} + continue + fi + mongodHackedArgs+=("$arg") + done + mongodHackedArgs+=("$newArg" "$val") +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg() { + local oldArg="$1"; shift + local newArg="$1"; shift + if _mongod_hack_have_arg "$oldArg" "$@"; then + _mongod_hack_ensure_no_arg "$oldArg" "$@" + _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" + fi +} + +# _js_escape 'some "string" value' +_js_escape() { + jq --null-input --arg 'str' "$1" '$str' +} + +jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" +tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" +_parse_config() { + if [ -s "$tempConfigFile" ]; then + return 0 + fi + + local configPath + if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then + # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) + # see https://docs.mongodb.com/manual/reference/configuration-options/ + mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" + jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" + return 0 + fi + + return 1 +} +dbPath= +_dbPath() { + if [ -n "$dbPath" ]; then + echo "$dbPath" + return + fi + + if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then + if _parse_config "$@"; then + dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" + fi + fi + + : "${dbPath:=/data/db}" + + echo "$dbPath" +} + +if [ "$originalArgOne" = 'mongod' ]; then + file_env 'MONGO_INITDB_ROOT_USERNAME' + file_env 'MONGO_INITDB_ROOT_PASSWORD' + # pre-check a few factors to see if it's even worth bothering with initdb + shouldPerformInitdb= + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + # if we have a username/password, let's set "--auth" + _mongod_hack_ensure_arg '--auth' "$@" + set -- "${mongodHackedArgs[@]}" + shouldPerformInitdb='true' + elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + cat >&2 <<-'EOF' + + error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' + both must be specified for a user to be created + + EOF + exit 1 + fi + + if [ -z "$shouldPerformInitdb" ]; then + # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh|*.js) # this should match the set of files we check for below + shouldPerformInitdb="$f" + break + ;; + esac + done + fi + + # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) + if [ -n "$shouldPerformInitdb" ]; then + dbPath="$(_dbPath "$@")" + for path in \ + "$dbPath/WiredTiger" \ + "$dbPath/journal" \ + "$dbPath/local.0" \ + "$dbPath/storage.bson" \ + ; do + if [ -e "$path" ]; then + shouldPerformInitdb= + break + fi + done + fi + + if [ -n "$shouldPerformInitdb" ]; then + mongodHackedArgs=( "$@" ) + _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" + + # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) + # https://github.com/docker-library/mongo/issues/211 + _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" + fi + + # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" + tlsMode='disabled' + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferSSL' + fi + # 4.2 switched all configuration/flag names from "SSL" to "TLS" + if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + else + _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + + if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then + # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 + # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 + _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" + else + initdbLogPath="$(_dbPath "$@")/docker-initdb.log" + echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" + _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" + fi + _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" + + pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" + rm -f "$pidfile" + _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" + + "${mongodHackedArgs[@]}" --fork + + mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) + + # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) + # https://jira.mongodb.org/browse/SERVER-16292 + tries=30 + while true; do + if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then + # bail ASAP if "mongod" isn't even running + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" + echo >&2 + exit 1 + fi + if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then + # success! + break + fi + (( tries-- )) + if [ "$tries" -le 0 ]; then + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" + echo >&2 + exit 1 + fi + sleep 1 + done + + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + rootAuthDatabase='admin' + + "${mongo[@]}" "$rootAuthDatabase" <<-EOJS + db.createUser({ + user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), + pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), + roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] + }) + EOJS + fi + + export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" + + echo + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + "${mongodHackedArgs[@]}" --shutdown + rm -f "$pidfile" + + echo + echo 'MongoDB init process complete; ready for start up.' + echo + fi + + mongodHackedArgs=("$@") + MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} + CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt + if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then + CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt + fi + if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then + CA="${MONGO_SSL_DIR}/ca.crt" + fi + if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem + _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" + if [ -f "${CA}" ]; then + _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" + fi + fi + MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} + if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem + _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" + if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then + _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" + fi + fi + + MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') + if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ]; then + _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" + + if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + tlsMode="none" + if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then + tlsMode='allowTLS' + elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then + tlsMode='requireTLS' + fi + + if [ "$tlsMode" != "none" ]; then + _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + fi + + _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" + if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" + fi + fi + _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" + + + _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" + fi + + set -- "${mongodHackedArgs[@]}" + + # MongoDB 3.6+ defaults to localhost-only binding + haveBindIp= + if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then + haveBindIp=1 + elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then + haveBindIp=1 + fi + if [ -z "$haveBindIp" ]; then + # so if no "--bind_ip" is specified, let's add "--bind_ip_all" + set -- "$@" --bind_ip_all + fi + + unset "${!MONGO_INITDB_@}" +fi + +rm -f "$jsonConfigFile" "$tempConfigFile" + +set -o xtrace +u + +exec "$@" \ No newline at end of file diff --git a/percona-server-mongodb-5.0-community/Dockerfile b/percona-server-mongodb-5.0-community/Dockerfile new file mode 100644 index 00000000..dce5d2ec --- /dev/null +++ b/percona-server-mongodb-5.0-community/Dockerfile @@ -0,0 +1,79 @@ +FROM redhat/ubi9-minimal + +LABEL name="MongoDB Community Edition" \ + release="5.0" \ + vendor="MongoDB Inc." \ + summary="MongoDB Community Edition with Percona operator compatibility" \ + description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ + maintainer="Percona Development " +LABEL org.opencontainers.image.authors="info@percona.com" + +ENV PSMDB_VERSION 5.0.28 +ENV OS_VER el9 + +# Do not report during Docker image creation. +ARG PERCONA_TELEMETRY_DISABLE=1 + +COPY mongodb.repo /etc/yum.repos.d/mongodb.repo + +RUN set -ex; \ + microdnf -y update glibc; \ + microdnf -y update libgcrypt; \ + microdnf -y install \ + mongodb-org-${PSMDB_VERSION} \ + mongodb-org-database-${PSMDB_VERSION} \ + mongodb-org-server-${PSMDB_VERSION} \ + mongodb-mongosh \ + mongodb-org-mongos-${PSMDB_VERSION} \ + mongodb-org-tools-${PSMDB_VERSION} \ + numactl \ + numactl-libs \ + procps-ng \ + jq \ + tar \ + oniguruma \ + cyrus-sasl-gssapi \ + cyrus-sasl-plain \ + policycoreutils; \ + microdnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ + chown -R 1001:0 /data/db + +# the numeric UID is needed for OpenShift +RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ + -c "Default Application User" mongodb; \ + chmod g+rwx /var/log/mongo; \ + chown :0 /var/log/mongo + +COPY LICENSE /licenses/LICENSE.Dockerfile +RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ + echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community + +ENV GOSU_VERSION=1.11 +RUN set -eux; \ + curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ + curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ + rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ + \ + chmod +x /usr/bin/gosu; \ + curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE + +VOLUME ["/data/db"] + +RUN set -ex; \ + curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ + echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - + +COPY ps-entry.sh /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] + +EXPOSE 27017 + +USER 1001 + +CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-5.0-community/LICENSE b/percona-server-mongodb-5.0-community/LICENSE new file mode 100644 index 00000000..0ae7afb4 --- /dev/null +++ b/percona-server-mongodb-5.0-community/LICENSE @@ -0,0 +1,7 @@ +MongoDB Community Edition License + +This software is licensed under the Server Side Public License (SSPL) v1. +For more information, see: https://www.mongodb.com/licensing/server-side-public-license + +This Docker image contains MongoDB Community Edition binaries and is configured +for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-5.0-community/mongodb.repo b/percona-server-mongodb-5.0-community/mongodb.repo new file mode 100644 index 00000000..2e50d35d --- /dev/null +++ b/percona-server-mongodb-5.0-community/mongodb.repo @@ -0,0 +1,6 @@ +[mongodb-org-5.0] +name=MongoDB Repository +baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/5.0/x86_64/ +gpgcheck=1 +enabled=1 +gpgkey=https://pgp.mongodb.com/server-5.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-5.0-community/ps-entry.sh b/percona-server-mongodb-5.0-community/ps-entry.sh new file mode 100644 index 00000000..89cb67af --- /dev/null +++ b/percona-server-mongodb-5.0-community/ps-entry.sh @@ -0,0 +1,462 @@ +#!/bin/bash +set -Eeuo pipefail + +if [ "${1:0:1}" = '-' ]; then + set -- mongod "$@" +fi + +originalArgOne="$1" + +# allow the container to be started with `--user` +# all mongo* commands should be dropped to the correct user +if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then + if [ "$originalArgOne" = 'mongod' ]; then + if [ -d "/data/configdb" ]; then + find /data/configdb \! -user mongodb -exec chown mongodb '{}' + + fi + if [ -d "/data/db" ]; then + find /data/db \! -user mongodb -exec chown mongodb '{}' + + fi + fi + + # make sure we can write to stdout and stderr as "mongodb" + # (for our "initdb" code later; see "--logpath" below) + chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : + # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 + + exec gosu mongodb:1001 "$BASH_SOURCE" "$@" +fi + +# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. +# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux +if [[ "$originalArgOne" == mongo* ]]; then + numa='numactl --interleave=all' + if $numa true &> /dev/null; then + set -- $numa "$@" + fi +fi + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) +_mongod_hack_have_arg() { + local checkArg="$1"; shift + local arg + for arg; do + case "$arg" in + "$checkArg"|"$checkArg"=*) + return 0 + ;; + esac + done + return 1 +} +# _mongod_hack_get_arg_val '--some-arg' "$@" +_mongod_hack_get_arg_val() { + local checkArg="$1"; shift + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$checkArg") + echo "$1" + return 0 + ;; + "$checkArg"=*) + echo "${arg#$checkArg=}" + return 0 + ;; + esac + done + return 1 +} +declare -a mongodHackedArgs +# _mongod_hack_ensure_arg '--some-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg() { + local ensureArg="$1"; shift + mongodHackedArgs=( "$@" ) + if ! _mongod_hack_have_arg "$ensureArg" "$@"; then + mongodHackedArgs+=( "$ensureArg" ) + fi +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$ensureNoArg" ]; then + continue + fi + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg_val() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$ensureNoArg") + shift # also skip the value + continue + ;; + "$ensureNoArg"=*) + # value is already included + continue + ;; + esac + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg_val() { + local ensureArg="$1"; shift + local ensureVal="$1"; shift + _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" + mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg_save_val() { + local oldArg="$1"; shift + local newArg="$1"; shift + if ! _mongod_hack_have_arg "$oldArg" "$@"; then + return 0 + fi + local val="" + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$oldArg" ]; then + val="$1"; shift + continue + elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then + val=${BASH_REMATCH[1]} + continue + fi + mongodHackedArgs+=("$arg") + done + mongodHackedArgs+=("$newArg" "$val") +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg() { + local oldArg="$1"; shift + local newArg="$1"; shift + if _mongod_hack_have_arg "$oldArg" "$@"; then + _mongod_hack_ensure_no_arg "$oldArg" "$@" + _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" + fi +} + +# _js_escape 'some "string" value' +_js_escape() { + jq --null-input --arg 'str' "$1" '$str' +} + +jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" +tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" +_parse_config() { + if [ -s "$tempConfigFile" ]; then + return 0 + fi + + local configPath + if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then + # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) + # see https://docs.mongodb.com/manual/reference/configuration-options/ + mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" + jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" + return 0 + fi + + return 1 +} +dbPath= +_dbPath() { + if [ -n "$dbPath" ]; then + echo "$dbPath" + return + fi + + if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then + if _parse_config "$@"; then + dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" + fi + fi + + : "${dbPath:=/data/db}" + + echo "$dbPath" +} + +if [ "$originalArgOne" = 'mongod' ]; then + file_env 'MONGO_INITDB_ROOT_USERNAME' + file_env 'MONGO_INITDB_ROOT_PASSWORD' + # pre-check a few factors to see if it's even worth bothering with initdb + shouldPerformInitdb= + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + # if we have a username/password, let's set "--auth" + _mongod_hack_ensure_arg '--auth' "$@" + set -- "${mongodHackedArgs[@]}" + shouldPerformInitdb='true' + elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + cat >&2 <<-'EOF' + + error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' + both must be specified for a user to be created + + EOF + exit 1 + fi + + if [ -z "$shouldPerformInitdb" ]; then + # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh|*.js) # this should match the set of files we check for below + shouldPerformInitdb="$f" + break + ;; + esac + done + fi + + # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) + if [ -n "$shouldPerformInitdb" ]; then + dbPath="$(_dbPath "$@")" + for path in \ + "$dbPath/WiredTiger" \ + "$dbPath/journal" \ + "$dbPath/local.0" \ + "$dbPath/storage.bson" \ + ; do + if [ -e "$path" ]; then + shouldPerformInitdb= + break + fi + done + fi + + if [ -n "$shouldPerformInitdb" ]; then + mongodHackedArgs=( "$@" ) + _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" + + # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) + # https://github.com/docker-library/mongo/issues/211 + _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" + fi + + # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" + tlsMode='disabled' + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferSSL' + fi + # 4.2 switched all configuration/flag names from "SSL" to "TLS" + if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + else + _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + + if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then + # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 + # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 + _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" + else + initdbLogPath="$(_dbPath "$@")/docker-initdb.log" + echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" + _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" + fi + _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" + + pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" + rm -f "$pidfile" + _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" + + "${mongodHackedArgs[@]}" --fork + + mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) + + # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) + # https://jira.mongodb.org/browse/SERVER-16292 + tries=30 + while true; do + if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then + # bail ASAP if "mongod" isn't even running + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" + echo >&2 + exit 1 + fi + if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then + # success! + break + fi + (( tries-- )) + if [ "$tries" -le 0 ]; then + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" + echo >&2 + exit 1 + fi + sleep 1 + done + + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + rootAuthDatabase='admin' + + "${mongo[@]}" "$rootAuthDatabase" <<-EOJS + db.createUser({ + user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), + pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), + roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] + }) + EOJS + fi + + export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" + + echo + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + "${mongodHackedArgs[@]}" --shutdown + rm -f "$pidfile" + + echo + echo 'MongoDB init process complete; ready for start up.' + echo + fi + + mongodHackedArgs=("$@") + MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} + CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt + if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then + CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt + fi + if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then + CA="${MONGO_SSL_DIR}/ca.crt" + fi + if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem + _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" + if [ -f "${CA}" ]; then + _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" + fi + fi + MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} + if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem + _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" + if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then + _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" + fi + fi + + MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') + if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ]; then + _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" + + if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + tlsMode="none" + if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then + tlsMode='allowTLS' + elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then + tlsMode='requireTLS' + fi + + if [ "$tlsMode" != "none" ]; then + _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + fi + + _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" + if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" + fi + fi + _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" + + + _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" + fi + + set -- "${mongodHackedArgs[@]}" + + # MongoDB 3.6+ defaults to localhost-only binding + haveBindIp= + if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then + haveBindIp=1 + elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then + haveBindIp=1 + fi + if [ -z "$haveBindIp" ]; then + # so if no "--bind_ip" is specified, let's add "--bind_ip_all" + set -- "$@" --bind_ip_all + fi + + unset "${!MONGO_INITDB_@}" +fi + +rm -f "$jsonConfigFile" "$tempConfigFile" + +set -o xtrace +u + +exec "$@" \ No newline at end of file diff --git a/percona-server-mongodb-6.0-community/Dockerfile b/percona-server-mongodb-6.0-community/Dockerfile new file mode 100644 index 00000000..a3f30f99 --- /dev/null +++ b/percona-server-mongodb-6.0-community/Dockerfile @@ -0,0 +1,79 @@ +FROM redhat/ubi9-minimal + +LABEL name="MongoDB Community Edition" \ + release="6.0" \ + vendor="MongoDB Inc." \ + summary="MongoDB Community Edition with Percona operator compatibility" \ + description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ + maintainer="Percona Development " +LABEL org.opencontainers.image.authors="info@percona.com" + +ENV PSMDB_VERSION 6.0.16 +ENV OS_VER el9 + +# Do not report during Docker image creation. +ARG PERCONA_TELEMETRY_DISABLE=1 + +COPY mongodb.repo /etc/yum.repos.d/mongodb.repo + +RUN set -ex; \ + microdnf -y update glibc; \ + microdnf -y update libgcrypt; \ + microdnf -y install \ + mongodb-org-${PSMDB_VERSION} \ + mongodb-org-database-${PSMDB_VERSION} \ + mongodb-org-server-${PSMDB_VERSION} \ + mongodb-mongosh \ + mongodb-org-mongos-${PSMDB_VERSION} \ + mongodb-org-tools-${PSMDB_VERSION} \ + numactl \ + numactl-libs \ + procps-ng \ + jq \ + tar \ + oniguruma \ + cyrus-sasl-gssapi \ + cyrus-sasl-plain \ + policycoreutils; \ + microdnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ + chown -R 1001:0 /data/db + +# the numeric UID is needed for OpenShift +RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ + -c "Default Application User" mongodb; \ + chmod g+rwx /var/log/mongo; \ + chown :0 /var/log/mongo + +COPY LICENSE /licenses/LICENSE.Dockerfile +RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ + echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community + +ENV GOSU_VERSION=1.11 +RUN set -eux; \ + curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ + curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ + rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ + \ + chmod +x /usr/bin/gosu; \ + curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE + +VOLUME ["/data/db"] + +RUN set -ex; \ + curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ + echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - + +COPY ps-entry.sh /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] + +EXPOSE 27017 + +USER 1001 + +CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-6.0-community/LICENSE b/percona-server-mongodb-6.0-community/LICENSE new file mode 100644 index 00000000..0ae7afb4 --- /dev/null +++ b/percona-server-mongodb-6.0-community/LICENSE @@ -0,0 +1,7 @@ +MongoDB Community Edition License + +This software is licensed under the Server Side Public License (SSPL) v1. +For more information, see: https://www.mongodb.com/licensing/server-side-public-license + +This Docker image contains MongoDB Community Edition binaries and is configured +for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-6.0-community/mongodb.repo b/percona-server-mongodb-6.0-community/mongodb.repo new file mode 100644 index 00000000..55321380 --- /dev/null +++ b/percona-server-mongodb-6.0-community/mongodb.repo @@ -0,0 +1,6 @@ +[mongodb-org-6.0] +name=MongoDB Repository +baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/6.0/x86_64/ +gpgcheck=1 +enabled=1 +gpgkey=https://pgp.mongodb.com/server-6.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-6.0-community/ps-entry.sh b/percona-server-mongodb-6.0-community/ps-entry.sh new file mode 100644 index 00000000..89cb67af --- /dev/null +++ b/percona-server-mongodb-6.0-community/ps-entry.sh @@ -0,0 +1,462 @@ +#!/bin/bash +set -Eeuo pipefail + +if [ "${1:0:1}" = '-' ]; then + set -- mongod "$@" +fi + +originalArgOne="$1" + +# allow the container to be started with `--user` +# all mongo* commands should be dropped to the correct user +if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then + if [ "$originalArgOne" = 'mongod' ]; then + if [ -d "/data/configdb" ]; then + find /data/configdb \! -user mongodb -exec chown mongodb '{}' + + fi + if [ -d "/data/db" ]; then + find /data/db \! -user mongodb -exec chown mongodb '{}' + + fi + fi + + # make sure we can write to stdout and stderr as "mongodb" + # (for our "initdb" code later; see "--logpath" below) + chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : + # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 + + exec gosu mongodb:1001 "$BASH_SOURCE" "$@" +fi + +# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. +# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux +if [[ "$originalArgOne" == mongo* ]]; then + numa='numactl --interleave=all' + if $numa true &> /dev/null; then + set -- $numa "$@" + fi +fi + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) +_mongod_hack_have_arg() { + local checkArg="$1"; shift + local arg + for arg; do + case "$arg" in + "$checkArg"|"$checkArg"=*) + return 0 + ;; + esac + done + return 1 +} +# _mongod_hack_get_arg_val '--some-arg' "$@" +_mongod_hack_get_arg_val() { + local checkArg="$1"; shift + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$checkArg") + echo "$1" + return 0 + ;; + "$checkArg"=*) + echo "${arg#$checkArg=}" + return 0 + ;; + esac + done + return 1 +} +declare -a mongodHackedArgs +# _mongod_hack_ensure_arg '--some-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg() { + local ensureArg="$1"; shift + mongodHackedArgs=( "$@" ) + if ! _mongod_hack_have_arg "$ensureArg" "$@"; then + mongodHackedArgs+=( "$ensureArg" ) + fi +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$ensureNoArg" ]; then + continue + fi + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg_val() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$ensureNoArg") + shift # also skip the value + continue + ;; + "$ensureNoArg"=*) + # value is already included + continue + ;; + esac + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg_val() { + local ensureArg="$1"; shift + local ensureVal="$1"; shift + _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" + mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg_save_val() { + local oldArg="$1"; shift + local newArg="$1"; shift + if ! _mongod_hack_have_arg "$oldArg" "$@"; then + return 0 + fi + local val="" + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$oldArg" ]; then + val="$1"; shift + continue + elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then + val=${BASH_REMATCH[1]} + continue + fi + mongodHackedArgs+=("$arg") + done + mongodHackedArgs+=("$newArg" "$val") +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg() { + local oldArg="$1"; shift + local newArg="$1"; shift + if _mongod_hack_have_arg "$oldArg" "$@"; then + _mongod_hack_ensure_no_arg "$oldArg" "$@" + _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" + fi +} + +# _js_escape 'some "string" value' +_js_escape() { + jq --null-input --arg 'str' "$1" '$str' +} + +jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" +tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" +_parse_config() { + if [ -s "$tempConfigFile" ]; then + return 0 + fi + + local configPath + if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then + # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) + # see https://docs.mongodb.com/manual/reference/configuration-options/ + mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" + jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" + return 0 + fi + + return 1 +} +dbPath= +_dbPath() { + if [ -n "$dbPath" ]; then + echo "$dbPath" + return + fi + + if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then + if _parse_config "$@"; then + dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" + fi + fi + + : "${dbPath:=/data/db}" + + echo "$dbPath" +} + +if [ "$originalArgOne" = 'mongod' ]; then + file_env 'MONGO_INITDB_ROOT_USERNAME' + file_env 'MONGO_INITDB_ROOT_PASSWORD' + # pre-check a few factors to see if it's even worth bothering with initdb + shouldPerformInitdb= + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + # if we have a username/password, let's set "--auth" + _mongod_hack_ensure_arg '--auth' "$@" + set -- "${mongodHackedArgs[@]}" + shouldPerformInitdb='true' + elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + cat >&2 <<-'EOF' + + error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' + both must be specified for a user to be created + + EOF + exit 1 + fi + + if [ -z "$shouldPerformInitdb" ]; then + # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh|*.js) # this should match the set of files we check for below + shouldPerformInitdb="$f" + break + ;; + esac + done + fi + + # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) + if [ -n "$shouldPerformInitdb" ]; then + dbPath="$(_dbPath "$@")" + for path in \ + "$dbPath/WiredTiger" \ + "$dbPath/journal" \ + "$dbPath/local.0" \ + "$dbPath/storage.bson" \ + ; do + if [ -e "$path" ]; then + shouldPerformInitdb= + break + fi + done + fi + + if [ -n "$shouldPerformInitdb" ]; then + mongodHackedArgs=( "$@" ) + _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" + + # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) + # https://github.com/docker-library/mongo/issues/211 + _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" + fi + + # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" + tlsMode='disabled' + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferSSL' + fi + # 4.2 switched all configuration/flag names from "SSL" to "TLS" + if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + else + _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + + if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then + # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 + # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 + _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" + else + initdbLogPath="$(_dbPath "$@")/docker-initdb.log" + echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" + _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" + fi + _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" + + pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" + rm -f "$pidfile" + _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" + + "${mongodHackedArgs[@]}" --fork + + mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) + + # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) + # https://jira.mongodb.org/browse/SERVER-16292 + tries=30 + while true; do + if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then + # bail ASAP if "mongod" isn't even running + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" + echo >&2 + exit 1 + fi + if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then + # success! + break + fi + (( tries-- )) + if [ "$tries" -le 0 ]; then + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" + echo >&2 + exit 1 + fi + sleep 1 + done + + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + rootAuthDatabase='admin' + + "${mongo[@]}" "$rootAuthDatabase" <<-EOJS + db.createUser({ + user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), + pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), + roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] + }) + EOJS + fi + + export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" + + echo + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + "${mongodHackedArgs[@]}" --shutdown + rm -f "$pidfile" + + echo + echo 'MongoDB init process complete; ready for start up.' + echo + fi + + mongodHackedArgs=("$@") + MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} + CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt + if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then + CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt + fi + if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then + CA="${MONGO_SSL_DIR}/ca.crt" + fi + if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem + _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" + if [ -f "${CA}" ]; then + _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" + fi + fi + MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} + if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem + _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" + if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then + _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" + fi + fi + + MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') + if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ]; then + _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" + + if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + tlsMode="none" + if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then + tlsMode='allowTLS' + elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then + tlsMode='requireTLS' + fi + + if [ "$tlsMode" != "none" ]; then + _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + fi + + _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" + if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" + fi + fi + _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" + + + _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" + fi + + set -- "${mongodHackedArgs[@]}" + + # MongoDB 3.6+ defaults to localhost-only binding + haveBindIp= + if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then + haveBindIp=1 + elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then + haveBindIp=1 + fi + if [ -z "$haveBindIp" ]; then + # so if no "--bind_ip" is specified, let's add "--bind_ip_all" + set -- "$@" --bind_ip_all + fi + + unset "${!MONGO_INITDB_@}" +fi + +rm -f "$jsonConfigFile" "$tempConfigFile" + +set -o xtrace +u + +exec "$@" \ No newline at end of file diff --git a/percona-server-mongodb-7.0-community/Dockerfile b/percona-server-mongodb-7.0-community/Dockerfile new file mode 100644 index 00000000..81d5420f --- /dev/null +++ b/percona-server-mongodb-7.0-community/Dockerfile @@ -0,0 +1,79 @@ +FROM redhat/ubi9-minimal + +LABEL name="MongoDB Community Edition" \ + release="7.0" \ + vendor="MongoDB Inc." \ + summary="MongoDB Community Edition with Percona operator compatibility" \ + description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ + maintainer="Percona Development " +LABEL org.opencontainers.image.authors="info@percona.com" + +ENV PSMDB_VERSION 7.0.14 +ENV OS_VER el9 + +# Do not report during Docker image creation. +ARG PERCONA_TELEMETRY_DISABLE=1 + +COPY mongodb.repo /etc/yum.repos.d/mongodb.repo + +RUN set -ex; \ + microdnf -y update glibc; \ + microdnf -y update libgcrypt; \ + microdnf -y install \ + mongodb-org-${PSMDB_VERSION} \ + mongodb-org-database-${PSMDB_VERSION} \ + mongodb-org-server-${PSMDB_VERSION} \ + mongodb-mongosh \ + mongodb-org-mongos-${PSMDB_VERSION} \ + mongodb-org-tools-${PSMDB_VERSION} \ + numactl \ + numactl-libs \ + procps-ng \ + jq \ + tar \ + oniguruma \ + cyrus-sasl-gssapi \ + cyrus-sasl-plain \ + policycoreutils; \ + microdnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ + chown -R 1001:0 /data/db + +# the numeric UID is needed for OpenShift +RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ + -c "Default Application User" mongodb; \ + chmod g+rwx /var/log/mongo; \ + chown :0 /var/log/mongo + +COPY LICENSE /licenses/LICENSE.Dockerfile +RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ + echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community + +ENV GOSU_VERSION=1.11 +RUN set -eux; \ + curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ + curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ + rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ + \ + chmod +x /usr/bin/gosu; \ + curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE + +VOLUME ["/data/db"] + +RUN set -ex; \ + curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ + echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - + +COPY ps-entry.sh /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] + +EXPOSE 27017 + +USER 1001 + +CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-7.0-community/LICENSE b/percona-server-mongodb-7.0-community/LICENSE new file mode 100644 index 00000000..0ae7afb4 --- /dev/null +++ b/percona-server-mongodb-7.0-community/LICENSE @@ -0,0 +1,7 @@ +MongoDB Community Edition License + +This software is licensed under the Server Side Public License (SSPL) v1. +For more information, see: https://www.mongodb.com/licensing/server-side-public-license + +This Docker image contains MongoDB Community Edition binaries and is configured +for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-7.0-community/mongodb.repo b/percona-server-mongodb-7.0-community/mongodb.repo new file mode 100644 index 00000000..5f74b3bc --- /dev/null +++ b/percona-server-mongodb-7.0-community/mongodb.repo @@ -0,0 +1,6 @@ +[mongodb-org-7.0] +name=MongoDB Repository +baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/7.0/x86_64/ +gpgcheck=1 +enabled=1 +gpgkey=https://pgp.mongodb.com/server-7.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-7.0-community/ps-entry.sh b/percona-server-mongodb-7.0-community/ps-entry.sh new file mode 100644 index 00000000..89cb67af --- /dev/null +++ b/percona-server-mongodb-7.0-community/ps-entry.sh @@ -0,0 +1,462 @@ +#!/bin/bash +set -Eeuo pipefail + +if [ "${1:0:1}" = '-' ]; then + set -- mongod "$@" +fi + +originalArgOne="$1" + +# allow the container to be started with `--user` +# all mongo* commands should be dropped to the correct user +if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then + if [ "$originalArgOne" = 'mongod' ]; then + if [ -d "/data/configdb" ]; then + find /data/configdb \! -user mongodb -exec chown mongodb '{}' + + fi + if [ -d "/data/db" ]; then + find /data/db \! -user mongodb -exec chown mongodb '{}' + + fi + fi + + # make sure we can write to stdout and stderr as "mongodb" + # (for our "initdb" code later; see "--logpath" below) + chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : + # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 + + exec gosu mongodb:1001 "$BASH_SOURCE" "$@" +fi + +# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. +# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux +if [[ "$originalArgOne" == mongo* ]]; then + numa='numactl --interleave=all' + if $numa true &> /dev/null; then + set -- $numa "$@" + fi +fi + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) +_mongod_hack_have_arg() { + local checkArg="$1"; shift + local arg + for arg; do + case "$arg" in + "$checkArg"|"$checkArg"=*) + return 0 + ;; + esac + done + return 1 +} +# _mongod_hack_get_arg_val '--some-arg' "$@" +_mongod_hack_get_arg_val() { + local checkArg="$1"; shift + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$checkArg") + echo "$1" + return 0 + ;; + "$checkArg"=*) + echo "${arg#$checkArg=}" + return 0 + ;; + esac + done + return 1 +} +declare -a mongodHackedArgs +# _mongod_hack_ensure_arg '--some-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg() { + local ensureArg="$1"; shift + mongodHackedArgs=( "$@" ) + if ! _mongod_hack_have_arg "$ensureArg" "$@"; then + mongodHackedArgs+=( "$ensureArg" ) + fi +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$ensureNoArg" ]; then + continue + fi + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg_val() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$ensureNoArg") + shift # also skip the value + continue + ;; + "$ensureNoArg"=*) + # value is already included + continue + ;; + esac + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg_val() { + local ensureArg="$1"; shift + local ensureVal="$1"; shift + _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" + mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg_save_val() { + local oldArg="$1"; shift + local newArg="$1"; shift + if ! _mongod_hack_have_arg "$oldArg" "$@"; then + return 0 + fi + local val="" + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$oldArg" ]; then + val="$1"; shift + continue + elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then + val=${BASH_REMATCH[1]} + continue + fi + mongodHackedArgs+=("$arg") + done + mongodHackedArgs+=("$newArg" "$val") +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg() { + local oldArg="$1"; shift + local newArg="$1"; shift + if _mongod_hack_have_arg "$oldArg" "$@"; then + _mongod_hack_ensure_no_arg "$oldArg" "$@" + _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" + fi +} + +# _js_escape 'some "string" value' +_js_escape() { + jq --null-input --arg 'str' "$1" '$str' +} + +jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" +tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" +_parse_config() { + if [ -s "$tempConfigFile" ]; then + return 0 + fi + + local configPath + if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then + # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) + # see https://docs.mongodb.com/manual/reference/configuration-options/ + mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" + jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" + return 0 + fi + + return 1 +} +dbPath= +_dbPath() { + if [ -n "$dbPath" ]; then + echo "$dbPath" + return + fi + + if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then + if _parse_config "$@"; then + dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" + fi + fi + + : "${dbPath:=/data/db}" + + echo "$dbPath" +} + +if [ "$originalArgOne" = 'mongod' ]; then + file_env 'MONGO_INITDB_ROOT_USERNAME' + file_env 'MONGO_INITDB_ROOT_PASSWORD' + # pre-check a few factors to see if it's even worth bothering with initdb + shouldPerformInitdb= + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + # if we have a username/password, let's set "--auth" + _mongod_hack_ensure_arg '--auth' "$@" + set -- "${mongodHackedArgs[@]}" + shouldPerformInitdb='true' + elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + cat >&2 <<-'EOF' + + error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' + both must be specified for a user to be created + + EOF + exit 1 + fi + + if [ -z "$shouldPerformInitdb" ]; then + # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh|*.js) # this should match the set of files we check for below + shouldPerformInitdb="$f" + break + ;; + esac + done + fi + + # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) + if [ -n "$shouldPerformInitdb" ]; then + dbPath="$(_dbPath "$@")" + for path in \ + "$dbPath/WiredTiger" \ + "$dbPath/journal" \ + "$dbPath/local.0" \ + "$dbPath/storage.bson" \ + ; do + if [ -e "$path" ]; then + shouldPerformInitdb= + break + fi + done + fi + + if [ -n "$shouldPerformInitdb" ]; then + mongodHackedArgs=( "$@" ) + _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" + + # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) + # https://github.com/docker-library/mongo/issues/211 + _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" + fi + + # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" + tlsMode='disabled' + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferSSL' + fi + # 4.2 switched all configuration/flag names from "SSL" to "TLS" + if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + else + _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + + if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then + # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 + # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 + _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" + else + initdbLogPath="$(_dbPath "$@")/docker-initdb.log" + echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" + _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" + fi + _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" + + pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" + rm -f "$pidfile" + _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" + + "${mongodHackedArgs[@]}" --fork + + mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) + + # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) + # https://jira.mongodb.org/browse/SERVER-16292 + tries=30 + while true; do + if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then + # bail ASAP if "mongod" isn't even running + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" + echo >&2 + exit 1 + fi + if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then + # success! + break + fi + (( tries-- )) + if [ "$tries" -le 0 ]; then + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" + echo >&2 + exit 1 + fi + sleep 1 + done + + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + rootAuthDatabase='admin' + + "${mongo[@]}" "$rootAuthDatabase" <<-EOJS + db.createUser({ + user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), + pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), + roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] + }) + EOJS + fi + + export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" + + echo + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + "${mongodHackedArgs[@]}" --shutdown + rm -f "$pidfile" + + echo + echo 'MongoDB init process complete; ready for start up.' + echo + fi + + mongodHackedArgs=("$@") + MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} + CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt + if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then + CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt + fi + if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then + CA="${MONGO_SSL_DIR}/ca.crt" + fi + if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem + _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" + if [ -f "${CA}" ]; then + _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" + fi + fi + MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} + if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem + _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" + if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then + _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" + fi + fi + + MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') + if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ]; then + _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" + + if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + tlsMode="none" + if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then + tlsMode='allowTLS' + elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then + tlsMode='requireTLS' + fi + + if [ "$tlsMode" != "none" ]; then + _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + fi + + _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" + if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" + fi + fi + _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" + + + _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" + fi + + set -- "${mongodHackedArgs[@]}" + + # MongoDB 3.6+ defaults to localhost-only binding + haveBindIp= + if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then + haveBindIp=1 + elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then + haveBindIp=1 + fi + if [ -z "$haveBindIp" ]; then + # so if no "--bind_ip" is specified, let's add "--bind_ip_all" + set -- "$@" --bind_ip_all + fi + + unset "${!MONGO_INITDB_@}" +fi + +rm -f "$jsonConfigFile" "$tempConfigFile" + +set -o xtrace +u + +exec "$@" \ No newline at end of file diff --git a/percona-server-mongodb-8.0-community/Dockerfile b/percona-server-mongodb-8.0-community/Dockerfile new file mode 100644 index 00000000..5ce574c4 --- /dev/null +++ b/percona-server-mongodb-8.0-community/Dockerfile @@ -0,0 +1,79 @@ +FROM redhat/ubi9-minimal + +LABEL name="MongoDB Community Edition" \ + release="8.0" \ + vendor="MongoDB Inc." \ + summary="MongoDB Community Edition with Percona operator compatibility" \ + description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ + maintainer="Percona Development " +LABEL org.opencontainers.image.authors="info@percona.com" + +ENV PSMDB_VERSION 8.0.3 +ENV OS_VER el9 + +# Do not report during Docker image creation. +ARG PERCONA_TELEMETRY_DISABLE=1 + +COPY mongodb.repo /etc/yum.repos.d/mongodb.repo + +RUN set -ex; \ + microdnf -y update glibc; \ + microdnf -y update libgcrypt; \ + microdnf -y install \ + mongodb-org-${PSMDB_VERSION} \ + mongodb-org-database-${PSMDB_VERSION} \ + mongodb-org-server-${PSMDB_VERSION} \ + mongodb-mongosh \ + mongodb-org-mongos-${PSMDB_VERSION} \ + mongodb-org-tools-${PSMDB_VERSION} \ + numactl \ + numactl-libs \ + procps-ng \ + jq \ + tar \ + oniguruma \ + cyrus-sasl-gssapi \ + cyrus-sasl-plain \ + policycoreutils; \ + microdnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ + chown -R 1001:0 /data/db + +# the numeric UID is needed for OpenShift +RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ + -c "Default Application User" mongodb; \ + chmod g+rwx /var/log/mongo; \ + chown :0 /var/log/mongo + +COPY LICENSE /licenses/LICENSE.Dockerfile +RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ + echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community + +ENV GOSU_VERSION=1.11 +RUN set -eux; \ + curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ + curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ + rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ + \ + chmod +x /usr/bin/gosu; \ + curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE + +VOLUME ["/data/db"] + +RUN set -ex; \ + curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ + echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - + +COPY ps-entry.sh /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] + +EXPOSE 27017 + +USER 1001 + +CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-8.0-community/LICENSE b/percona-server-mongodb-8.0-community/LICENSE new file mode 100644 index 00000000..0ae7afb4 --- /dev/null +++ b/percona-server-mongodb-8.0-community/LICENSE @@ -0,0 +1,7 @@ +MongoDB Community Edition License + +This software is licensed under the Server Side Public License (SSPL) v1. +For more information, see: https://www.mongodb.com/licensing/server-side-public-license + +This Docker image contains MongoDB Community Edition binaries and is configured +for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-8.0-community/mongodb.repo b/percona-server-mongodb-8.0-community/mongodb.repo new file mode 100644 index 00000000..656f03b5 --- /dev/null +++ b/percona-server-mongodb-8.0-community/mongodb.repo @@ -0,0 +1,6 @@ +[mongodb-org-8.0] +name=MongoDB Repository +baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/8.0/x86_64/ +gpgcheck=1 +enabled=1 +gpgkey=https://pgp.mongodb.com/server-8.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-8.0-community/ps-entry.sh b/percona-server-mongodb-8.0-community/ps-entry.sh new file mode 100644 index 00000000..e22a3bce --- /dev/null +++ b/percona-server-mongodb-8.0-community/ps-entry.sh @@ -0,0 +1,462 @@ +#!/bin/bash +set -Eeuo pipefail + +if [ "${1:0:1}" = '-' ]; then + set -- mongod "$@" +fi + +originalArgOne="$1" + +# allow the container to be started with `--user` +# all mongo* commands should be dropped to the correct user +if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then + if [ "$originalArgOne" = 'mongod' ]; then + if [ -d "/data/configdb" ]; then + find /data/configdb \! -user mongodb -exec chown mongodb '{}' + + fi + if [ -d "/data/db" ]; then + find /data/db \! -user mongodb -exec chown mongodb '{}' + + fi + fi + + # make sure we can write to stdout and stderr as "mongodb" + # (for our "initdb" code later; see "--logpath" below) + chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : + # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 + + exec gosu mongodb:1001 "$BASH_SOURCE" "$@" +fi + +# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. +# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux +if [[ "$originalArgOne" == mongo* ]]; then + numa='numactl --interleave=all' + if $numa true &> /dev/null; then + set -- $numa "$@" + fi +fi + +# usage: file_env VAR [DEFAULT] +# ie: file_env 'XYZ_DB_PASSWORD' 'example' +# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of +# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + export "$var"="$val" + unset "$fileVar" +} + +# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) +_mongod_hack_have_arg() { + local checkArg="$1"; shift + local arg + for arg; do + case "$arg" in + "$checkArg"|"$checkArg"=*) + return 0 + ;; + esac + done + return 1 +} +# _mongod_hack_get_arg_val '--some-arg' "$@" +_mongod_hack_get_arg_val() { + local checkArg="$1"; shift + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$checkArg") + echo "$1" + return 0 + ;; + "$checkArg"=*) + echo "${arg#$checkArg=}" + return 0 + ;; + esac + done + return 1 +} +declare -a mongodHackedArgs +# _mongod_hack_ensure_arg '--some-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg() { + local ensureArg="$1"; shift + mongodHackedArgs=( "$@" ) + if ! _mongod_hack_have_arg "$ensureArg" "$@"; then + mongodHackedArgs+=( "$ensureArg" ) + fi +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$ensureNoArg" ]; then + continue + fi + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_no_arg_val() { + local ensureNoArg="$1"; shift + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + case "$arg" in + "$ensureNoArg") + shift # also skip the value + continue + ;; + "$ensureNoArg"=*) + # value is already included + continue + ;; + esac + mongodHackedArgs+=( "$arg" ) + done +} +# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_ensure_arg_val() { + local ensureArg="$1"; shift + local ensureVal="$1"; shift + _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" + mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg_save_val() { + local oldArg="$1"; shift + local newArg="$1"; shift + if ! _mongod_hack_have_arg "$oldArg" "$@"; then + return 0 + fi + local val="" + mongodHackedArgs=() + while [ "$#" -gt 0 ]; do + local arg="$1"; shift + if [ "$arg" = "$oldArg" ]; then + val="$1"; shift + continue + elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then + val=${BASH_REMATCH[1]} + continue + fi + mongodHackedArgs+=("$arg") + done + mongodHackedArgs+=("$newArg" "$val") +} + +# required by mongodb 4.2 +# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" +# set -- "${mongodHackedArgs[@]}" +_mongod_hack_rename_arg() { + local oldArg="$1"; shift + local newArg="$1"; shift + if _mongod_hack_have_arg "$oldArg" "$@"; then + _mongod_hack_ensure_no_arg "$oldArg" "$@" + _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" + fi +} + +# _js_escape 'some "string" value' +_js_escape() { + jq --null-input --arg 'str' "$1" '$str' +} + +jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" +tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" +_parse_config() { + if [ -s "$tempConfigFile" ]; then + return 0 + fi + + local configPath + if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then + # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) + # see https://docs.mongodb.com/manual/reference/configuration-options/ + mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" + jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" + return 0 + fi + + return 1 +} +dbPath= +_dbPath() { + if [ -n "$dbPath" ]; then + echo "$dbPath" + return + fi + + if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then + if _parse_config "$@"; then + dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" + fi + fi + + : "${dbPath:=/data/db}" + + echo "$dbPath" +} + +if [ "$originalArgOne" = 'mongod' ]; then + file_env 'MONGO_INITDB_ROOT_USERNAME' + file_env 'MONGO_INITDB_ROOT_PASSWORD' + # pre-check a few factors to see if it's even worth bothering with initdb + shouldPerformInitdb= + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + # if we have a username/password, let's set "--auth" + _mongod_hack_ensure_arg '--auth' "$@" + set -- "${mongodHackedArgs[@]}" + shouldPerformInitdb='true' + elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + cat >&2 <<-'EOF' + + error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' + both must be specified for a user to be created + + EOF + exit 1 + fi + + if [ -z "$shouldPerformInitdb" ]; then + # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh|*.js) # this should match the set of files we check for below + shouldPerformInitdb="$f" + break + ;; + esac + done + fi + + # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) + if [ -n "$shouldPerformInitdb" ]; then + dbPath="$(_dbPath "$@")" + for path in \ + "$dbPath/WiredTiger" \ + "$dbPath/journal" \ + "$dbPath/local.0" \ + "$dbPath/storage.bson" \ + ; do + if [ -e "$path" ]; then + shouldPerformInitdb= + break + fi + done + fi + + if [ -n "$shouldPerformInitdb" ]; then + mongodHackedArgs=( "$@" ) + _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" + _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" + + # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) + # https://github.com/docker-library/mongo/issues/211 + _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" + fi + + # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" + tlsMode='disabled' + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then + tlsMode='preferSSL' + fi + # 4.2 switched all configuration/flag names from "SSL" to "TLS" + if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + else + _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + + if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then + # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 + # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 + _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" + else + initdbLogPath="$(_dbPath "$@")/docker-initdb.log" + echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" + _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" + fi + _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" + + pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" + rm -f "$pidfile" + _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" + + "${mongodHackedArgs[@]}" --fork + + mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) + + # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) + # https://jira.mongodb.org/browse/SERVER-16292 + tries=30 + while true; do + if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then + # bail ASAP if "mongod" isn't even running + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" + echo >&2 + exit 1 + fi + if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then + # success! + break + fi + (( tries-- )) + if [ "$tries" -le 0 ]; then + echo >&2 + echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" + echo >&2 + exit 1 + fi + sleep 1 + done + + if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then + rootAuthDatabase='admin' + + "${mongo[@]}" "$rootAuthDatabase" <<-EOJS + db.createUser({ + user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), + pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), + roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] + }) + EOJS + fi + + export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" + + echo + for f in /docker-entrypoint-initdb.d/*; do + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo + done + + "${mongodHackedArgs[@]}" --shutdown + rm -f "$pidfile" + + echo + echo 'MongoDB init process complete; ready for start up.' + echo + fi + + mongodHackedArgs=("$@") + MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} + CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt + if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then + CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt + fi + if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then + CA="${MONGO_SSL_DIR}/ca.crt" + fi + if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem + _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" + if [ -f "${CA}" ]; then + _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" + fi + fi + MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} + if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then + cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem + _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" + if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then + _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" + fi + fi + + MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') + if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ] || [ "$MONGODB_VERSION" == 'v8.0' ]; then + _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" + + if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + tlsMode="none" + if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then + tlsMode='allowTLS' + elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then + tlsMode='preferTLS' + elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then + tlsMode='requireTLS' + fi + + if [ "$tlsMode" != "none" ]; then + _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" + _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" + fi + fi + + _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" + if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then + if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then + _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" + fi + fi + _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" + + + _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" + _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" + fi + + set -- "${mongodHackedArgs[@]}" + + # MongoDB 3.6+ defaults to localhost-only binding + haveBindIp= + if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then + haveBindIp=1 + elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then + haveBindIp=1 + fi + if [ -z "$haveBindIp" ]; then + # so if no "--bind_ip" is specified, let's add "--bind_ip_all" + set -- "$@" --bind_ip_all + fi + + unset "${!MONGO_INITDB_@}" +fi + +rm -f "$jsonConfigFile" "$tempConfigFile" + +set -o xtrace +u + +exec "$@" \ No newline at end of file From 6e9e255262d693294c2c8150e11539249cb4c644 Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Thu, 15 Jan 2026 09:53:48 -0700 Subject: [PATCH 02/10] Try to fix up 8.0-community --- .../mongodb.repo | 2 +- .../mongodb.repo | 2 +- .../mongodb.repo | 2 +- .../mongodb.repo | 2 +- .../Dockerfile | 19 +- .../Dockerfile.k8s | 198 +++++ .../mongodb.repo | 8 +- .../ps-entry.sh | 717 +++++++----------- 8 files changed, 494 insertions(+), 456 deletions(-) create mode 100644 percona-server-mongodb-8.0-community/Dockerfile.k8s diff --git a/percona-server-mongodb-4.4-community/mongodb.repo b/percona-server-mongodb-4.4-community/mongodb.repo index 7b2f9361..b679dad4 100644 --- a/percona-server-mongodb-4.4-community/mongodb.repo +++ b/percona-server-mongodb-4.4-community/mongodb.repo @@ -1,6 +1,6 @@ [mongodb-org-4.4] name=MongoDB Repository -baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/4.4/x86_64/ +baseurl=https://repo.mongodb.com/yum/amazon/2023/mongodb-org/4.4/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/server-4.4.asc \ No newline at end of file diff --git a/percona-server-mongodb-5.0-community/mongodb.repo b/percona-server-mongodb-5.0-community/mongodb.repo index 2e50d35d..4528cf53 100644 --- a/percona-server-mongodb-5.0-community/mongodb.repo +++ b/percona-server-mongodb-5.0-community/mongodb.repo @@ -1,6 +1,6 @@ [mongodb-org-5.0] name=MongoDB Repository -baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/5.0/x86_64/ +baseurl=https://repo.mongodb.com/yum/amazon/2023/mongodb-org/5.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/server-5.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-6.0-community/mongodb.repo b/percona-server-mongodb-6.0-community/mongodb.repo index 55321380..cb62000d 100644 --- a/percona-server-mongodb-6.0-community/mongodb.repo +++ b/percona-server-mongodb-6.0-community/mongodb.repo @@ -1,6 +1,6 @@ [mongodb-org-6.0] name=MongoDB Repository -baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/6.0/x86_64/ +baseurl=https://repo.mongodb.com/yum/amazon/2023/mongodb-org/6.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/server-6.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-7.0-community/mongodb.repo b/percona-server-mongodb-7.0-community/mongodb.repo index 5f74b3bc..c32d12f2 100644 --- a/percona-server-mongodb-7.0-community/mongodb.repo +++ b/percona-server-mongodb-7.0-community/mongodb.repo @@ -1,6 +1,6 @@ [mongodb-org-7.0] name=MongoDB Repository -baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/7.0/x86_64/ +baseurl=https://repo.mongodb.com/yum/amazon/2023/mongodb-org/7.0/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/server-7.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-8.0-community/Dockerfile b/percona-server-mongodb-8.0-community/Dockerfile index 5ce574c4..50a73b21 100644 --- a/percona-server-mongodb-8.0-community/Dockerfile +++ b/percona-server-mongodb-8.0-community/Dockerfile @@ -8,8 +8,8 @@ LABEL name="MongoDB Community Edition" \ maintainer="Percona Development " LABEL org.opencontainers.image.authors="info@percona.com" -ENV PSMDB_VERSION 8.0.3 -ENV OS_VER el9 +ENV PSMDB_VERSION=8.0.3 +ENV OS_VER=el9 # Do not report during Docker image creation. ARG PERCONA_TELEMETRY_DISABLE=1 @@ -17,8 +17,7 @@ ARG PERCONA_TELEMETRY_DISABLE=1 COPY mongodb.repo /etc/yum.repos.d/mongodb.repo RUN set -ex; \ - microdnf -y update glibc; \ - microdnf -y update libgcrypt; \ + microdnf -y update; \ microdnf -y install \ mongodb-org-${PSMDB_VERSION} \ mongodb-org-database-${PSMDB_VERSION} \ @@ -26,24 +25,23 @@ RUN set -ex; \ mongodb-mongosh \ mongodb-org-mongos-${PSMDB_VERSION} \ mongodb-org-tools-${PSMDB_VERSION} \ - numactl \ numactl-libs \ procps-ng \ jq \ tar \ oniguruma \ cyrus-sasl-gssapi \ - cyrus-sasl-plain \ - policycoreutils; \ + cyrus-sasl-plain; \ microdnf clean all; \ - rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ + rm -rf /var/cache/yum /data/db && mkdir -p /data/db; \ chown -R 1001:0 /data/db # the numeric UID is needed for OpenShift RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ -c "Default Application User" mongodb; \ - chmod g+rwx /var/log/mongo; \ - chown :0 /var/log/mongo + mkdir -p /var/log/mongo /etc/mongodb; \ + chmod g+rwx /var/log/mongo /etc/mongodb; \ + chown :0 /var/log/mongo /etc/mongodb COPY LICENSE /licenses/LICENSE.Dockerfile RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ @@ -69,6 +67,7 @@ RUN set -ex; \ echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - COPY ps-entry.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh ENTRYPOINT ["/entrypoint.sh"] diff --git a/percona-server-mongodb-8.0-community/Dockerfile.k8s b/percona-server-mongodb-8.0-community/Dockerfile.k8s new file mode 100644 index 00000000..01b5e8ea --- /dev/null +++ b/percona-server-mongodb-8.0-community/Dockerfile.k8s @@ -0,0 +1,198 @@ +# Multi-architecture MongoDB Community Edition for Kubernetes +# This Dockerfile is optimized for Kubernetes deployments with multi-arch support + +ARG TARGETARCH +ARG TARGETOS +ARG TARGETPLATFORM + +FROM --platform=${TARGETPLATFORM} redhat/ubi9-minimal + +# Kubernetes and OpenShift compatibility labels +LABEL name="MongoDB Community Edition for Kubernetes" \ + release="8.0" \ + version="8.0.3" \ + vendor="MongoDB Inc." \ + summary="MongoDB Community Edition optimized for Kubernetes with Percona operator compatibility" \ + description="Multi-architecture MongoDB Community Edition container optimized for Kubernetes deployments. Includes enhanced security, health checks, and operator integration." \ + maintainer="Percona Development " \ + io.k8s.description="MongoDB Community Edition for Kubernetes" \ + io.k8s.display-name="MongoDB Community 8.0" \ + io.openshift.expose-services="27017:mongodb" \ + io.openshift.tags="database,mongodb,nosql" + +LABEL org.opencontainers.image.title="MongoDB Community Edition for Kubernetes" \ + org.opencontainers.image.description="Multi-architecture MongoDB Community Edition optimized for Kubernetes" \ + org.opencontainers.image.version="8.0.3" \ + org.opencontainers.image.authors="info@percona.com" \ + org.opencontainers.image.vendor="Percona" \ + org.opencontainers.image.licenses="SSPL-1.0" \ + org.opencontainers.image.source="https://github.com/percona/percona-docker" \ + org.opencontainers.image.documentation="https://docs.percona.com/" + +# Environment variables for MongoDB and Kubernetes +ENV PSMDB_VERSION=8.0.3 \ + OS_VER=el9 \ + MONGODB_VERSION=8.0 \ + GOSU_VERSION=1.17 \ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +# Kubernetes-specific environment variables +ENV MONGODB_DATA_DIR=/data/db \ + MONGODB_LOG_DIR=/var/log/mongodb \ + MONGODB_CONFIG_DIR=/etc/mongodb \ + MONGODB_USER=mongodb \ + MONGODB_UID=1001 \ + MONGODB_GID=0 + +# Security and telemetry settings +ARG PERCONA_TELEMETRY_DISABLE=1 +ENV PERCONA_TELEMETRY_DISABLE=${PERCONA_TELEMETRY_DISABLE} + +# Copy repository configuration with architecture detection +COPY mongodb.repo /etc/yum.repos.d/mongodb.repo + +# Install MongoDB and dependencies with multi-arch support +RUN set -ex; \ + # Update system packages + microdnf -y update; \ + \ + # Install required system packages + microdnf -y install \ + shadow-utils \ + findutils \ + tar \ + gzip \ + procps-ng; \ + \ + # Install MongoDB packages + microdnf -y install \ + mongodb-org-${PSMDB_VERSION} \ + mongodb-org-database-${PSMDB_VERSION} \ + mongodb-org-server-${PSMDB_VERSION} \ + mongodb-mongosh \ + mongodb-org-mongos-${PSMDB_VERSION} \ + mongodb-org-tools-${PSMDB_VERSION} \ + numactl-libs \ + jq \ + oniguruma \ + cyrus-sasl-gssapi \ + cyrus-sasl-plain; \ + \ + # Clean up package cache + microdnf clean all; \ + rm -rf /var/cache/yum; \ + \ + # Create necessary directories with proper permissions + mkdir -p ${MONGODB_DATA_DIR} ${MONGODB_LOG_DIR} ${MONGODB_CONFIG_DIR} /tmp/mongodb; \ + \ + # Set up directory permissions for Kubernetes/OpenShift + chown -R ${MONGODB_UID}:${MONGODB_GID} ${MONGODB_DATA_DIR} ${MONGODB_LOG_DIR} ${MONGODB_CONFIG_DIR} /tmp/mongodb; \ + chmod -R g+rwx ${MONGODB_DATA_DIR} ${MONGODB_LOG_DIR} ${MONGODB_CONFIG_DIR} /tmp/mongodb; \ + chmod -R o-rwx ${MONGODB_DATA_DIR} ${MONGODB_LOG_DIR} ${MONGODB_CONFIG_DIR} + +# Create MongoDB user with Kubernetes/OpenShift compatibility +RUN set -ex; \ + # Create mongodb user with specific UID for Kubernetes + useradd -u ${MONGODB_UID} -r -g ${MONGODB_GID} -m -s /sbin/nologin \ + -c "MongoDB Application User" -d /home/mongodb ${MONGODB_USER}; \ + \ + # Ensure proper ownership and permissions + chown -R ${MONGODB_UID}:${MONGODB_GID} /home/mongodb; \ + chmod -R g+rwx /home/mongodb + +# Install gosu for privilege dropping with multi-arch support +RUN set -eux; \ + ARCH=$(uname -m); \ + case "$ARCH" in \ + x86_64) GOSU_ARCH="amd64" ;; \ + aarch64) GOSU_ARCH="arm64" ;; \ + *) echo "Unsupported architecture for gosu: $ARCH" && exit 1 ;; \ + esac; \ + \ + curl -fsSL -o /usr/bin/gosu "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${GOSU_ARCH}"; \ + curl -fsSL -o /usr/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${GOSU_ARCH}.asc"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ + rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ + \ + chmod +x /usr/bin/gosu; \ + gosu --version; \ + gosu nobody true + +# Install js-yaml for configuration parsing +RUN set -ex; \ + curl -fsSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ + echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c -; \ + chmod 644 /js-yaml.js + +# Copy license files +COPY LICENSE /licenses/LICENSE.Dockerfile +RUN set -ex; \ + mkdir -p /licenses; \ + cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community 2>/dev/null || \ + echo "MongoDB Community License (SSPL-1.0)" > /licenses/LICENSE.MongoDB-Community; \ + curl -fsSL -o /licenses/LICENSE.gosu "https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE"; \ + chmod 644 /licenses/* + +# Copy entrypoint and health check scripts +COPY ps-entry.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh + +# Set up scripts with proper permissions +RUN set -ex; \ + chmod +x /entrypoint.sh /healthcheck.sh; \ + chown ${MONGODB_UID}:${MONGODB_GID} /entrypoint.sh /healthcheck.sh + +# Create MongoDB configuration template +RUN set -ex; \ + cat > ${MONGODB_CONFIG_DIR}/mongod.conf.template << 'EOF' +# MongoDB configuration file template for Kubernetes +storage: + dbPath: /data/db + wiredTiger: + engineConfig: + cacheSizeGB: 0.25 + +systemLog: + destination: file + logAppend: true + path: /var/log/mongodb/mongod.log + logRotate: reopen + +net: + port: 27017 + bindIpAll: true + +processManagement: + timeZoneInfo: /usr/share/zoneinfo + +security: + authorization: disabled + +replication: + replSetName: rs0 + +operationProfiling: + slowOpThresholdMs: 100 +EOF + +# Set up health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ + CMD /healthcheck.sh + +# Kubernetes-specific volume declarations +VOLUME ["${MONGODB_DATA_DIR}", "${MONGODB_LOG_DIR}"] + +# Expose MongoDB port +EXPOSE 27017 + +# Use entrypoint for MongoDB initialization +ENTRYPOINT ["/entrypoint.sh"] + +# Switch to non-root user +USER ${MONGODB_UID} + +# Default command +CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-8.0-community/mongodb.repo b/percona-server-mongodb-8.0-community/mongodb.repo index 656f03b5..235f6f68 100644 --- a/percona-server-mongodb-8.0-community/mongodb.repo +++ b/percona-server-mongodb-8.0-community/mongodb.repo @@ -1,6 +1,10 @@ [mongodb-org-8.0] name=MongoDB Repository -baseurl=https://repo.mongodb.org/yum/redhat/8/mongodb-org/8.0/x86_64/ +baseurl=https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.0/$basearch/ gpgcheck=1 enabled=1 -gpgkey=https://pgp.mongodb.com/server-8.0.asc \ No newline at end of file +gpgkey=https://pgp.mongodb.com/server-8.0.asc +sslverify=1 +sslcacert=/etc/pki/tls/certs/ca-bundle.crt +metadata_expire=300 +repo_gpgcheck=1 diff --git a/percona-server-mongodb-8.0-community/ps-entry.sh b/percona-server-mongodb-8.0-community/ps-entry.sh index e22a3bce..c82289f7 100644 --- a/percona-server-mongodb-8.0-community/ps-entry.sh +++ b/percona-server-mongodb-8.0-community/ps-entry.sh @@ -1,462 +1,299 @@ #!/bin/bash -set -Eeuo pipefail - -if [ "${1:0:1}" = '-' ]; then - set -- mongod "$@" -fi +# Enhanced MongoDB Entrypoint Script for Kubernetes +# Optimized for Kubernetes deployments with improved signal handling, configuration management, and operator integration -originalArgOne="$1" +set -Eeuo pipefail -# allow the container to be started with `--user` -# all mongo* commands should be dropped to the correct user -if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then - if [ "$originalArgOne" = 'mongod' ]; then - if [ -d "/data/configdb" ]; then - find /data/configdb \! -user mongodb -exec chown mongodb '{}' + - fi - if [ -d "/data/db" ]; then - find /data/db \! -user mongodb -exec chown mongodb '{}' + - fi - fi +# Configuration variables +MONGODB_DATA_DIR="${MONGODB_DATA_DIR:-/data/db}" +MONGODB_LOG_DIR="${MONGODB_LOG_DIR:-/var/log/mongodb}" +MONGODB_CONFIG_DIR="${MONGODB_CONFIG_DIR:-/etc/mongodb}" +MONGODB_USER="${MONGODB_USER:-mongodb}" +MONGODB_UID="${MONGODB_UID:-1001}" +MONGODB_GID="${MONGODB_GID:-0}" + +# Kubernetes-specific variables +K8S_NAMESPACE="${K8S_NAMESPACE:-}" +K8S_POD_NAME="${K8S_POD_NAME:-}" +K8S_SERVICE_NAME="${K8S_SERVICE_NAME:-}" +REPLICA_SET_NAME="${REPLICA_SET_NAME:-rs0}" + +# Logging function +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] ENTRYPOINT: $*" >&2 +} - # make sure we can write to stdout and stderr as "mongodb" - # (for our "initdb" code later; see "--logpath" below) - chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : - # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 +# Error handling +error_exit() { + log "ERROR: $1" + exit 1 +} - exec gosu mongodb:1001 "$BASH_SOURCE" "$@" -fi +# Signal handling for graceful shutdown +shutdown_handler() { + log "Received shutdown signal, initiating graceful shutdown..." + + # If MongoDB is running, try to shut it down gracefully + if pgrep -f mongod >/dev/null 2>&1; then + log "Shutting down MongoDB gracefully..." + + # Try to use MongoDB's shutdown command first + if mongosh --quiet --eval "db.adminCommand('shutdown')" >/dev/null 2>&1; then + log "MongoDB shutdown command sent successfully" + else + log "MongoDB shutdown command failed, sending SIGTERM to process" + pkill -TERM mongod || true + fi + + # Wait for process to exit gracefully + local timeout=30 + while pgrep -f mongod >/dev/null 2>&1 && [ $timeout -gt 0 ]; do + sleep 1 + timeout=$((timeout - 1)) + done + + if pgrep -f mongod >/dev/null 2>&1; then + log "MongoDB did not shut down gracefully, sending SIGKILL" + pkill -KILL mongod || true + else + log "MongoDB shut down gracefully" + fi + fi + + exit 0 +} -# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. -# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux -if [[ "$originalArgOne" == mongo* ]]; then - numa='numactl --interleave=all' - if $numa true &> /dev/null; then - set -- $numa "$@" - fi -fi +# Set up signal handlers +trap shutdown_handler SIGTERM SIGINT SIGQUIT + +# Function to setup directories and permissions +setup_directories() { + log "Setting up directories and permissions..." + + # Create necessary directories + for dir in "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" "$MONGODB_CONFIG_DIR" "/tmp/mongodb"; do + if [[ ! -d "$dir" ]]; then + mkdir -p "$dir" + log "Created directory: $dir" + fi + done + + # Set ownership and permissions for Kubernetes/OpenShift compatibility + chown -R "$MONGODB_UID:$MONGODB_GID" "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" "$MONGODB_CONFIG_DIR" "/tmp/mongodb" 2>/dev/null || true + chmod -R g+rwx "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" "$MONGODB_CONFIG_DIR" "/tmp/mongodb" 2>/dev/null || true + chmod -R o-rwx "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" "$MONGODB_CONFIG_DIR" 2>/dev/null || true +} -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) +# Function to handle file-based environment variables (Kubernetes secrets) file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + + if [[ -n "${!var:-}" ]] && [[ -n "${!fileVar:-}" ]]; then + error_exit "Both $var and $fileVar are set (but are exclusive)" + fi + + local val="$def" + if [[ -n "${!var:-}" ]]; then + val="${!var}" + elif [[ -n "${!fileVar:-}" ]]; then + if [[ -f "${!fileVar}" ]]; then + val="$(< "${!fileVar}")" + else + error_exit "File ${!fileVar} does not exist" + fi + fi + + export "$var"="$val" + unset "$fileVar" 2>/dev/null || true } -# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) -_mongod_hack_have_arg() { - local checkArg="$1"; shift - local arg - for arg; do - case "$arg" in - "$checkArg"|"$checkArg"=*) - return 0 - ;; - esac - done - return 1 -} -# _mongod_hack_get_arg_val '--some-arg' "$@" -_mongod_hack_get_arg_val() { - local checkArg="$1"; shift - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$checkArg") - echo "$1" - return 0 - ;; - "$checkArg"=*) - echo "${arg#$checkArg=}" - return 0 - ;; - esac - done - return 1 -} -declare -a mongodHackedArgs -# _mongod_hack_ensure_arg '--some-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg() { - local ensureArg="$1"; shift - mongodHackedArgs=( "$@" ) - if ! _mongod_hack_have_arg "$ensureArg" "$@"; then - mongodHackedArgs+=( "$ensureArg" ) - fi -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$ensureNoArg" ]; then - continue - fi - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg_val() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$ensureNoArg") - shift # also skip the value - continue - ;; - "$ensureNoArg"=*) - # value is already included - continue - ;; - esac - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg_val() { - local ensureArg="$1"; shift - local ensureVal="$1"; shift - _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" - mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) +# Function to generate MongoDB configuration +generate_config() { + local config_file="$MONGODB_CONFIG_DIR/mongod.conf" + + log "Generating MongoDB configuration..." + + # Start with template if it exists + if [[ -f "$MONGODB_CONFIG_DIR/mongod.conf.template" ]]; then + cp "$MONGODB_CONFIG_DIR/mongod.conf.template" "$config_file" + else + # Create basic configuration + cat > "$config_file" << EOF +# MongoDB configuration for Kubernetes +storage: + dbPath: $MONGODB_DATA_DIR + journal: + enabled: true + +systemLog: + destination: file + logAppend: true + path: $MONGODB_LOG_DIR/mongod.log + logRotate: reopen + +net: + port: 27017 + bindIpAll: true + +processManagement: + timeZoneInfo: /usr/share/zoneinfo + +security: + authorization: disabled +EOF + fi + + # Add replica set configuration if specified + if [[ -n "$REPLICA_SET_NAME" ]]; then + if ! grep -q "replication:" "$config_file"; then + cat >> "$config_file" << EOF + +replication: + replSetName: $REPLICA_SET_NAME +EOF + fi + fi + + # Set proper permissions + chown "$MONGODB_UID:$MONGODB_GID" "$config_file" + chmod 640 "$config_file" + + log "MongoDB configuration generated at $config_file" } -# required by mongodb 4.2 -# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg_save_val() { - local oldArg="$1"; shift - local newArg="$1"; shift - if ! _mongod_hack_have_arg "$oldArg" "$@"; then - return 0 - fi - local val="" - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$oldArg" ]; then - val="$1"; shift - continue - elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then - val=${BASH_REMATCH[1]} - continue - fi - mongodHackedArgs+=("$arg") - done - mongodHackedArgs+=("$newArg" "$val") +# Function to wait for network readiness +wait_for_network() { + log "Waiting for network readiness..." + + local timeout=30 + while [ $timeout -gt 0 ]; do + if ss -tuln | grep -q ":27017 "; then + log "Port 27017 is already in use, waiting..." + sleep 1 + timeout=$((timeout - 1)) + else + break + fi + done + + if [ $timeout -eq 0 ]; then + log "Warning: Port 27017 may still be in use" + fi } -# required by mongodb 4.2 -# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg() { - local oldArg="$1"; shift - local newArg="$1"; shift - if _mongod_hack_have_arg "$oldArg" "$@"; then - _mongod_hack_ensure_no_arg "$oldArg" "$@" - _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" - fi +# Function to initialize MongoDB if needed +initialize_mongodb() { + log "Checking if MongoDB initialization is needed..." + + # Check if this is a fresh installation + if [[ ! -f "$MONGODB_DATA_DIR/WiredTiger" ]] && [[ ! -f "$MONGODB_DATA_DIR/mongod.lock" ]]; then + log "Fresh MongoDB installation detected" + + # Handle initialization scripts + file_env 'MONGO_INITDB_ROOT_USERNAME' + file_env 'MONGO_INITDB_ROOT_PASSWORD' + file_env 'MONGO_INITDB_DATABASE' + + if [[ -n "${MONGO_INITDB_ROOT_USERNAME:-}" ]] && [[ -n "${MONGO_INITDB_ROOT_PASSWORD:-}" ]]; then + log "Root user credentials provided, will initialize with authentication" + export MONGO_INITDB_ROOT_USERNAME + export MONGO_INITDB_ROOT_PASSWORD + export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-admin}" + fi + else + log "Existing MongoDB data found, skipping initialization" + fi } -# _js_escape 'some "string" value' -_js_escape() { - jq --null-input --arg 'str' "$1" '$str' +# Function to setup MongoDB arguments with Kubernetes optimizations +setup_mongodb_args() { + local -a mongod_args=("$@") + + # If no arguments provided, use default + if [[ ${#mongod_args[@]} -eq 0 ]]; then + mongod_args=("mongod") + fi + + # If first argument starts with -, prepend mongod + if [[ "${mongod_args[0]:0:1}" = '-' ]]; then + mongod_args=("mongod" "${mongod_args[@]}") + fi + + # Add Kubernetes-specific optimizations + local -a k8s_args=() + + # Use configuration file if it exists + if [[ -f "$MONGODB_CONFIG_DIR/mongod.conf" ]]; then + k8s_args+=("--config" "$MONGODB_CONFIG_DIR/mongod.conf") + fi + + # Kubernetes-specific settings + k8s_args+=( + "--bind_ip_all" + "--logpath" "$MONGODB_LOG_DIR/mongod.log" + "--logappend" + ) + + # Add NUMA optimization if available + if command -v numactl >/dev/null 2>&1 && numactl --hardware >/dev/null 2>&1; then + mongod_args=("numactl" "--interleave=all" "${mongod_args[@]}") + fi + + # Combine arguments + mongod_args+=("${k8s_args[@]}") + + echo "${mongod_args[@]}" } -jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" -tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" -_parse_config() { - if [ -s "$tempConfigFile" ]; then - return 0 - fi - - local configPath - if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then - # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) - # see https://docs.mongodb.com/manual/reference/configuration-options/ - mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" - jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" - return 0 - fi - - return 1 +# Function to start MongoDB with proper user switching +start_mongodb() { + local -a mongod_cmd=($@) + + log "Starting MongoDB with command: ${mongod_cmd[*]}" + + # Ensure we're running as the correct user + if [[ "$(id -u)" = '0' ]]; then + # Running as root, switch to mongodb user + log "Running as root, switching to user $MONGODB_USER (UID: $MONGODB_UID)" + + # Ensure ownership of critical files + chown "$MONGODB_UID:$MONGODB_GID" "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" 2>/dev/null || true + + # Use gosu to switch user and exec + exec gosu "$MONGODB_UID:$MONGODB_GID" "${mongod_cmd[@]}" + else + # Already running as non-root user + log "Running as user $(id -un) (UID: $(id -u))" + exec "${mongod_cmd[@]}" + fi } -dbPath= -_dbPath() { - if [ -n "$dbPath" ]; then - echo "$dbPath" - return - fi - - if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then - if _parse_config "$@"; then - dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" - fi - fi - : "${dbPath:=/data/db}" - - echo "$dbPath" +# Main execution function +main() { + log "Starting MongoDB entrypoint for Kubernetes..." + log "Pod: ${K8S_POD_NAME:-unknown}, Namespace: ${K8S_NAMESPACE:-unknown}" + + # Setup directories and permissions + setup_directories + + # Wait for network readiness + wait_for_network + + # Generate configuration + generate_config + + # Initialize MongoDB if needed + initialize_mongodb + + # Setup MongoDB arguments + local -a final_args + IFS=' ' read -ra final_args <<< "$(setup_mongodb_args "$@")" + + # Start MongoDB + start_mongodb "${final_args[@]}" } -if [ "$originalArgOne" = 'mongod' ]; then - file_env 'MONGO_INITDB_ROOT_USERNAME' - file_env 'MONGO_INITDB_ROOT_PASSWORD' - # pre-check a few factors to see if it's even worth bothering with initdb - shouldPerformInitdb= - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - # if we have a username/password, let's set "--auth" - _mongod_hack_ensure_arg '--auth' "$@" - set -- "${mongodHackedArgs[@]}" - shouldPerformInitdb='true' - elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - cat >&2 <<-'EOF' - - error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' - both must be specified for a user to be created - - EOF - exit 1 - fi - - if [ -z "$shouldPerformInitdb" ]; then - # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh|*.js) # this should match the set of files we check for below - shouldPerformInitdb="$f" - break - ;; - esac - done - fi - - # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) - if [ -n "$shouldPerformInitdb" ]; then - dbPath="$(_dbPath "$@")" - for path in \ - "$dbPath/WiredTiger" \ - "$dbPath/journal" \ - "$dbPath/local.0" \ - "$dbPath/storage.bson" \ - ; do - if [ -e "$path" ]; then - shouldPerformInitdb= - break - fi - done - fi - - if [ -n "$shouldPerformInitdb" ]; then - mongodHackedArgs=( "$@" ) - _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" - - # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) - # https://github.com/docker-library/mongo/issues/211 - _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" - fi - - # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" - tlsMode='disabled' - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferSSL' - fi - # 4.2 switched all configuration/flag names from "SSL" to "TLS" - if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - else - _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - - if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then - # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 - # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 - _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" - else - initdbLogPath="$(_dbPath "$@")/docker-initdb.log" - echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" - _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" - fi - _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" - - pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" - rm -f "$pidfile" - _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" - - "${mongodHackedArgs[@]}" --fork - - mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) - - # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) - # https://jira.mongodb.org/browse/SERVER-16292 - tries=30 - while true; do - if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then - # bail ASAP if "mongod" isn't even running - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" - echo >&2 - exit 1 - fi - if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then - # success! - break - fi - (( tries-- )) - if [ "$tries" -le 0 ]; then - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" - echo >&2 - exit 1 - fi - sleep 1 - done - - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - rootAuthDatabase='admin' - - "${mongo[@]}" "$rootAuthDatabase" <<-EOJS - db.createUser({ - user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), - pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), - roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] - }) - EOJS - fi - - export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - "${mongodHackedArgs[@]}" --shutdown - rm -f "$pidfile" - - echo - echo 'MongoDB init process complete; ready for start up.' - echo - fi - - mongodHackedArgs=("$@") - MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} - CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt - if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then - CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt - fi - if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then - CA="${MONGO_SSL_DIR}/ca.crt" - fi - if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem - _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" - if [ -f "${CA}" ]; then - _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" - fi - fi - MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} - if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem - _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" - if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then - _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" - fi - fi - - MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') - if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ] || [ "$MONGODB_VERSION" == 'v8.0' ]; then - _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" - - if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - tlsMode="none" - if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then - tlsMode='allowTLS' - elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then - tlsMode='requireTLS' - fi - - if [ "$tlsMode" != "none" ]; then - _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - fi - - _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" - if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" - fi - fi - _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" - - - _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" - fi - - set -- "${mongodHackedArgs[@]}" - - # MongoDB 3.6+ defaults to localhost-only binding - haveBindIp= - if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then - haveBindIp=1 - elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then - haveBindIp=1 - fi - if [ -z "$haveBindIp" ]; then - # so if no "--bind_ip" is specified, let's add "--bind_ip_all" - set -- "$@" --bind_ip_all - fi - - unset "${!MONGO_INITDB_@}" -fi - -rm -f "$jsonConfigFile" "$tempConfigFile" - -set -o xtrace +u - -exec "$@" \ No newline at end of file +# Execute main function with all arguments +main "$@" \ No newline at end of file From 248f41db31e023a550c795f0d2cf067a9280f0cb Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Thu, 15 Jan 2026 18:04:31 -0700 Subject: [PATCH 03/10] Remove mongodb 4.4-community --- .../Dockerfile | 79 --- percona-server-mongodb-4.4-community/LICENSE | 7 - .../mongodb.repo | 6 - .../ps-entry.sh | 462 ------------------ 4 files changed, 554 deletions(-) delete mode 100644 percona-server-mongodb-4.4-community/Dockerfile delete mode 100644 percona-server-mongodb-4.4-community/LICENSE delete mode 100644 percona-server-mongodb-4.4-community/mongodb.repo delete mode 100644 percona-server-mongodb-4.4-community/ps-entry.sh diff --git a/percona-server-mongodb-4.4-community/Dockerfile b/percona-server-mongodb-4.4-community/Dockerfile deleted file mode 100644 index 0c1b268c..00000000 --- a/percona-server-mongodb-4.4-community/Dockerfile +++ /dev/null @@ -1,79 +0,0 @@ -FROM redhat/ubi9-minimal - -LABEL name="MongoDB Community Edition" \ - release="4.4" \ - vendor="MongoDB Inc." \ - summary="MongoDB Community Edition with Percona operator compatibility" \ - description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ - maintainer="Percona Development " -LABEL org.opencontainers.image.authors="info@percona.com" - -ENV PSMDB_VERSION 4.4.29 -ENV OS_VER el9 - -# Do not report during Docker image creation. -ARG PERCONA_TELEMETRY_DISABLE=1 - -COPY mongodb.repo /etc/yum.repos.d/mongodb.repo - -RUN set -ex; \ - microdnf -y update glibc; \ - microdnf -y update libgcrypt; \ - microdnf -y install \ - mongodb-org-${PSMDB_VERSION} \ - mongodb-org-database-${PSMDB_VERSION} \ - mongodb-org-server-${PSMDB_VERSION} \ - mongodb-mongosh \ - mongodb-org-mongos-${PSMDB_VERSION} \ - mongodb-org-tools-${PSMDB_VERSION} \ - numactl \ - numactl-libs \ - procps-ng \ - jq \ - tar \ - oniguruma \ - cyrus-sasl-gssapi \ - cyrus-sasl-plain \ - policycoreutils; \ - microdnf clean all; \ - rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ - chown -R 1001:0 /data/db - -# the numeric UID is needed for OpenShift -RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ - -c "Default Application User" mongodb; \ - chmod g+rwx /var/log/mongo; \ - chown :0 /var/log/mongo - -COPY LICENSE /licenses/LICENSE.Dockerfile -RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ - echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community - -ENV GOSU_VERSION=1.11 -RUN set -eux; \ - curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ - curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ - \ - export GNUPGHOME="$(mktemp -d)"; \ - gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ - gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ - rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ - \ - chmod +x /usr/bin/gosu; \ - curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE - -VOLUME ["/data/db"] - -RUN set -ex; \ - curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ - echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - - -COPY ps-entry.sh /entrypoint.sh - -ENTRYPOINT ["/entrypoint.sh"] - -EXPOSE 27017 - -USER 1001 - -CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-4.4-community/LICENSE b/percona-server-mongodb-4.4-community/LICENSE deleted file mode 100644 index 0ae7afb4..00000000 --- a/percona-server-mongodb-4.4-community/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -MongoDB Community Edition License - -This software is licensed under the Server Side Public License (SSPL) v1. -For more information, see: https://www.mongodb.com/licensing/server-side-public-license - -This Docker image contains MongoDB Community Edition binaries and is configured -for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-4.4-community/mongodb.repo b/percona-server-mongodb-4.4-community/mongodb.repo deleted file mode 100644 index b679dad4..00000000 --- a/percona-server-mongodb-4.4-community/mongodb.repo +++ /dev/null @@ -1,6 +0,0 @@ -[mongodb-org-4.4] -name=MongoDB Repository -baseurl=https://repo.mongodb.com/yum/amazon/2023/mongodb-org/4.4/x86_64/ -gpgcheck=1 -enabled=1 -gpgkey=https://pgp.mongodb.com/server-4.4.asc \ No newline at end of file diff --git a/percona-server-mongodb-4.4-community/ps-entry.sh b/percona-server-mongodb-4.4-community/ps-entry.sh deleted file mode 100644 index 89cb67af..00000000 --- a/percona-server-mongodb-4.4-community/ps-entry.sh +++ /dev/null @@ -1,462 +0,0 @@ -#!/bin/bash -set -Eeuo pipefail - -if [ "${1:0:1}" = '-' ]; then - set -- mongod "$@" -fi - -originalArgOne="$1" - -# allow the container to be started with `--user` -# all mongo* commands should be dropped to the correct user -if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then - if [ "$originalArgOne" = 'mongod' ]; then - if [ -d "/data/configdb" ]; then - find /data/configdb \! -user mongodb -exec chown mongodb '{}' + - fi - if [ -d "/data/db" ]; then - find /data/db \! -user mongodb -exec chown mongodb '{}' + - fi - fi - - # make sure we can write to stdout and stderr as "mongodb" - # (for our "initdb" code later; see "--logpath" below) - chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : - # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 - - exec gosu mongodb:1001 "$BASH_SOURCE" "$@" -fi - -# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. -# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux -if [[ "$originalArgOne" == mongo* ]]; then - numa='numactl --interleave=all' - if $numa true &> /dev/null; then - set -- $numa "$@" - fi -fi - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) -_mongod_hack_have_arg() { - local checkArg="$1"; shift - local arg - for arg; do - case "$arg" in - "$checkArg"|"$checkArg"=*) - return 0 - ;; - esac - done - return 1 -} -# _mongod_hack_get_arg_val '--some-arg' "$@" -_mongod_hack_get_arg_val() { - local checkArg="$1"; shift - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$checkArg") - echo "$1" - return 0 - ;; - "$checkArg"=*) - echo "${arg#$checkArg=}" - return 0 - ;; - esac - done - return 1 -} -declare -a mongodHackedArgs -# _mongod_hack_ensure_arg '--some-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg() { - local ensureArg="$1"; shift - mongodHackedArgs=( "$@" ) - if ! _mongod_hack_have_arg "$ensureArg" "$@"; then - mongodHackedArgs+=( "$ensureArg" ) - fi -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$ensureNoArg" ]; then - continue - fi - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg_val() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$ensureNoArg") - shift # also skip the value - continue - ;; - "$ensureNoArg"=*) - # value is already included - continue - ;; - esac - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg_val() { - local ensureArg="$1"; shift - local ensureVal="$1"; shift - _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" - mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) -} - -# required by mongodb 4.2 -# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg_save_val() { - local oldArg="$1"; shift - local newArg="$1"; shift - if ! _mongod_hack_have_arg "$oldArg" "$@"; then - return 0 - fi - local val="" - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$oldArg" ]; then - val="$1"; shift - continue - elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then - val=${BASH_REMATCH[1]} - continue - fi - mongodHackedArgs+=("$arg") - done - mongodHackedArgs+=("$newArg" "$val") -} - -# required by mongodb 4.2 -# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg() { - local oldArg="$1"; shift - local newArg="$1"; shift - if _mongod_hack_have_arg "$oldArg" "$@"; then - _mongod_hack_ensure_no_arg "$oldArg" "$@" - _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" - fi -} - -# _js_escape 'some "string" value' -_js_escape() { - jq --null-input --arg 'str' "$1" '$str' -} - -jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" -tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" -_parse_config() { - if [ -s "$tempConfigFile" ]; then - return 0 - fi - - local configPath - if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then - # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) - # see https://docs.mongodb.com/manual/reference/configuration-options/ - mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" - jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" - return 0 - fi - - return 1 -} -dbPath= -_dbPath() { - if [ -n "$dbPath" ]; then - echo "$dbPath" - return - fi - - if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then - if _parse_config "$@"; then - dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" - fi - fi - - : "${dbPath:=/data/db}" - - echo "$dbPath" -} - -if [ "$originalArgOne" = 'mongod' ]; then - file_env 'MONGO_INITDB_ROOT_USERNAME' - file_env 'MONGO_INITDB_ROOT_PASSWORD' - # pre-check a few factors to see if it's even worth bothering with initdb - shouldPerformInitdb= - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - # if we have a username/password, let's set "--auth" - _mongod_hack_ensure_arg '--auth' "$@" - set -- "${mongodHackedArgs[@]}" - shouldPerformInitdb='true' - elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - cat >&2 <<-'EOF' - - error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' - both must be specified for a user to be created - - EOF - exit 1 - fi - - if [ -z "$shouldPerformInitdb" ]; then - # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh|*.js) # this should match the set of files we check for below - shouldPerformInitdb="$f" - break - ;; - esac - done - fi - - # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) - if [ -n "$shouldPerformInitdb" ]; then - dbPath="$(_dbPath "$@")" - for path in \ - "$dbPath/WiredTiger" \ - "$dbPath/journal" \ - "$dbPath/local.0" \ - "$dbPath/storage.bson" \ - ; do - if [ -e "$path" ]; then - shouldPerformInitdb= - break - fi - done - fi - - if [ -n "$shouldPerformInitdb" ]; then - mongodHackedArgs=( "$@" ) - _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" - - # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) - # https://github.com/docker-library/mongo/issues/211 - _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" - fi - - # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" - tlsMode='disabled' - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferSSL' - fi - # 4.2 switched all configuration/flag names from "SSL" to "TLS" - if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - else - _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - - if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then - # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 - # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 - _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" - else - initdbLogPath="$(_dbPath "$@")/docker-initdb.log" - echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" - _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" - fi - _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" - - pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" - rm -f "$pidfile" - _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" - - "${mongodHackedArgs[@]}" --fork - - mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) - - # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) - # https://jira.mongodb.org/browse/SERVER-16292 - tries=30 - while true; do - if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then - # bail ASAP if "mongod" isn't even running - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" - echo >&2 - exit 1 - fi - if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then - # success! - break - fi - (( tries-- )) - if [ "$tries" -le 0 ]; then - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" - echo >&2 - exit 1 - fi - sleep 1 - done - - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - rootAuthDatabase='admin' - - "${mongo[@]}" "$rootAuthDatabase" <<-EOJS - db.createUser({ - user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), - pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), - roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] - }) - EOJS - fi - - export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - "${mongodHackedArgs[@]}" --shutdown - rm -f "$pidfile" - - echo - echo 'MongoDB init process complete; ready for start up.' - echo - fi - - mongodHackedArgs=("$@") - MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} - CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt - if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then - CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt - fi - if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then - CA="${MONGO_SSL_DIR}/ca.crt" - fi - if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem - _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" - if [ -f "${CA}" ]; then - _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" - fi - fi - MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} - if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem - _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" - if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then - _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" - fi - fi - - MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') - if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ]; then - _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" - - if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - tlsMode="none" - if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then - tlsMode='allowTLS' - elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then - tlsMode='requireTLS' - fi - - if [ "$tlsMode" != "none" ]; then - _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - fi - - _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" - if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" - fi - fi - _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" - - - _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" - fi - - set -- "${mongodHackedArgs[@]}" - - # MongoDB 3.6+ defaults to localhost-only binding - haveBindIp= - if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then - haveBindIp=1 - elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then - haveBindIp=1 - fi - if [ -z "$haveBindIp" ]; then - # so if no "--bind_ip" is specified, let's add "--bind_ip_all" - set -- "$@" --bind_ip_all - fi - - unset "${!MONGO_INITDB_@}" -fi - -rm -f "$jsonConfigFile" "$tempConfigFile" - -set -o xtrace +u - -exec "$@" \ No newline at end of file From 89bfdc4ea7c29f81f9456ed3257ed8fc9e85709b Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Thu, 15 Jan 2026 18:05:12 -0700 Subject: [PATCH 04/10] Remove mongodb 5.0-community --- .../Dockerfile | 79 --- percona-server-mongodb-5.0-community/LICENSE | 7 - .../mongodb.repo | 6 - .../ps-entry.sh | 462 ------------------ 4 files changed, 554 deletions(-) delete mode 100644 percona-server-mongodb-5.0-community/Dockerfile delete mode 100644 percona-server-mongodb-5.0-community/LICENSE delete mode 100644 percona-server-mongodb-5.0-community/mongodb.repo delete mode 100644 percona-server-mongodb-5.0-community/ps-entry.sh diff --git a/percona-server-mongodb-5.0-community/Dockerfile b/percona-server-mongodb-5.0-community/Dockerfile deleted file mode 100644 index dce5d2ec..00000000 --- a/percona-server-mongodb-5.0-community/Dockerfile +++ /dev/null @@ -1,79 +0,0 @@ -FROM redhat/ubi9-minimal - -LABEL name="MongoDB Community Edition" \ - release="5.0" \ - vendor="MongoDB Inc." \ - summary="MongoDB Community Edition with Percona operator compatibility" \ - description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ - maintainer="Percona Development " -LABEL org.opencontainers.image.authors="info@percona.com" - -ENV PSMDB_VERSION 5.0.28 -ENV OS_VER el9 - -# Do not report during Docker image creation. -ARG PERCONA_TELEMETRY_DISABLE=1 - -COPY mongodb.repo /etc/yum.repos.d/mongodb.repo - -RUN set -ex; \ - microdnf -y update glibc; \ - microdnf -y update libgcrypt; \ - microdnf -y install \ - mongodb-org-${PSMDB_VERSION} \ - mongodb-org-database-${PSMDB_VERSION} \ - mongodb-org-server-${PSMDB_VERSION} \ - mongodb-mongosh \ - mongodb-org-mongos-${PSMDB_VERSION} \ - mongodb-org-tools-${PSMDB_VERSION} \ - numactl \ - numactl-libs \ - procps-ng \ - jq \ - tar \ - oniguruma \ - cyrus-sasl-gssapi \ - cyrus-sasl-plain \ - policycoreutils; \ - microdnf clean all; \ - rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ - chown -R 1001:0 /data/db - -# the numeric UID is needed for OpenShift -RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ - -c "Default Application User" mongodb; \ - chmod g+rwx /var/log/mongo; \ - chown :0 /var/log/mongo - -COPY LICENSE /licenses/LICENSE.Dockerfile -RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ - echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community - -ENV GOSU_VERSION=1.11 -RUN set -eux; \ - curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ - curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ - \ - export GNUPGHOME="$(mktemp -d)"; \ - gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ - gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ - rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ - \ - chmod +x /usr/bin/gosu; \ - curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE - -VOLUME ["/data/db"] - -RUN set -ex; \ - curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ - echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - - -COPY ps-entry.sh /entrypoint.sh - -ENTRYPOINT ["/entrypoint.sh"] - -EXPOSE 27017 - -USER 1001 - -CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-5.0-community/LICENSE b/percona-server-mongodb-5.0-community/LICENSE deleted file mode 100644 index 0ae7afb4..00000000 --- a/percona-server-mongodb-5.0-community/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -MongoDB Community Edition License - -This software is licensed under the Server Side Public License (SSPL) v1. -For more information, see: https://www.mongodb.com/licensing/server-side-public-license - -This Docker image contains MongoDB Community Edition binaries and is configured -for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-5.0-community/mongodb.repo b/percona-server-mongodb-5.0-community/mongodb.repo deleted file mode 100644 index 4528cf53..00000000 --- a/percona-server-mongodb-5.0-community/mongodb.repo +++ /dev/null @@ -1,6 +0,0 @@ -[mongodb-org-5.0] -name=MongoDB Repository -baseurl=https://repo.mongodb.com/yum/amazon/2023/mongodb-org/5.0/x86_64/ -gpgcheck=1 -enabled=1 -gpgkey=https://pgp.mongodb.com/server-5.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-5.0-community/ps-entry.sh b/percona-server-mongodb-5.0-community/ps-entry.sh deleted file mode 100644 index 89cb67af..00000000 --- a/percona-server-mongodb-5.0-community/ps-entry.sh +++ /dev/null @@ -1,462 +0,0 @@ -#!/bin/bash -set -Eeuo pipefail - -if [ "${1:0:1}" = '-' ]; then - set -- mongod "$@" -fi - -originalArgOne="$1" - -# allow the container to be started with `--user` -# all mongo* commands should be dropped to the correct user -if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then - if [ "$originalArgOne" = 'mongod' ]; then - if [ -d "/data/configdb" ]; then - find /data/configdb \! -user mongodb -exec chown mongodb '{}' + - fi - if [ -d "/data/db" ]; then - find /data/db \! -user mongodb -exec chown mongodb '{}' + - fi - fi - - # make sure we can write to stdout and stderr as "mongodb" - # (for our "initdb" code later; see "--logpath" below) - chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : - # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 - - exec gosu mongodb:1001 "$BASH_SOURCE" "$@" -fi - -# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. -# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux -if [[ "$originalArgOne" == mongo* ]]; then - numa='numactl --interleave=all' - if $numa true &> /dev/null; then - set -- $numa "$@" - fi -fi - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) -_mongod_hack_have_arg() { - local checkArg="$1"; shift - local arg - for arg; do - case "$arg" in - "$checkArg"|"$checkArg"=*) - return 0 - ;; - esac - done - return 1 -} -# _mongod_hack_get_arg_val '--some-arg' "$@" -_mongod_hack_get_arg_val() { - local checkArg="$1"; shift - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$checkArg") - echo "$1" - return 0 - ;; - "$checkArg"=*) - echo "${arg#$checkArg=}" - return 0 - ;; - esac - done - return 1 -} -declare -a mongodHackedArgs -# _mongod_hack_ensure_arg '--some-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg() { - local ensureArg="$1"; shift - mongodHackedArgs=( "$@" ) - if ! _mongod_hack_have_arg "$ensureArg" "$@"; then - mongodHackedArgs+=( "$ensureArg" ) - fi -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$ensureNoArg" ]; then - continue - fi - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg_val() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$ensureNoArg") - shift # also skip the value - continue - ;; - "$ensureNoArg"=*) - # value is already included - continue - ;; - esac - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg_val() { - local ensureArg="$1"; shift - local ensureVal="$1"; shift - _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" - mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) -} - -# required by mongodb 4.2 -# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg_save_val() { - local oldArg="$1"; shift - local newArg="$1"; shift - if ! _mongod_hack_have_arg "$oldArg" "$@"; then - return 0 - fi - local val="" - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$oldArg" ]; then - val="$1"; shift - continue - elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then - val=${BASH_REMATCH[1]} - continue - fi - mongodHackedArgs+=("$arg") - done - mongodHackedArgs+=("$newArg" "$val") -} - -# required by mongodb 4.2 -# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg() { - local oldArg="$1"; shift - local newArg="$1"; shift - if _mongod_hack_have_arg "$oldArg" "$@"; then - _mongod_hack_ensure_no_arg "$oldArg" "$@" - _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" - fi -} - -# _js_escape 'some "string" value' -_js_escape() { - jq --null-input --arg 'str' "$1" '$str' -} - -jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" -tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" -_parse_config() { - if [ -s "$tempConfigFile" ]; then - return 0 - fi - - local configPath - if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then - # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) - # see https://docs.mongodb.com/manual/reference/configuration-options/ - mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" - jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" - return 0 - fi - - return 1 -} -dbPath= -_dbPath() { - if [ -n "$dbPath" ]; then - echo "$dbPath" - return - fi - - if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then - if _parse_config "$@"; then - dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" - fi - fi - - : "${dbPath:=/data/db}" - - echo "$dbPath" -} - -if [ "$originalArgOne" = 'mongod' ]; then - file_env 'MONGO_INITDB_ROOT_USERNAME' - file_env 'MONGO_INITDB_ROOT_PASSWORD' - # pre-check a few factors to see if it's even worth bothering with initdb - shouldPerformInitdb= - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - # if we have a username/password, let's set "--auth" - _mongod_hack_ensure_arg '--auth' "$@" - set -- "${mongodHackedArgs[@]}" - shouldPerformInitdb='true' - elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - cat >&2 <<-'EOF' - - error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' - both must be specified for a user to be created - - EOF - exit 1 - fi - - if [ -z "$shouldPerformInitdb" ]; then - # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh|*.js) # this should match the set of files we check for below - shouldPerformInitdb="$f" - break - ;; - esac - done - fi - - # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) - if [ -n "$shouldPerformInitdb" ]; then - dbPath="$(_dbPath "$@")" - for path in \ - "$dbPath/WiredTiger" \ - "$dbPath/journal" \ - "$dbPath/local.0" \ - "$dbPath/storage.bson" \ - ; do - if [ -e "$path" ]; then - shouldPerformInitdb= - break - fi - done - fi - - if [ -n "$shouldPerformInitdb" ]; then - mongodHackedArgs=( "$@" ) - _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" - - # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) - # https://github.com/docker-library/mongo/issues/211 - _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" - fi - - # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" - tlsMode='disabled' - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferSSL' - fi - # 4.2 switched all configuration/flag names from "SSL" to "TLS" - if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - else - _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - - if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then - # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 - # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 - _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" - else - initdbLogPath="$(_dbPath "$@")/docker-initdb.log" - echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" - _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" - fi - _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" - - pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" - rm -f "$pidfile" - _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" - - "${mongodHackedArgs[@]}" --fork - - mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) - - # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) - # https://jira.mongodb.org/browse/SERVER-16292 - tries=30 - while true; do - if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then - # bail ASAP if "mongod" isn't even running - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" - echo >&2 - exit 1 - fi - if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then - # success! - break - fi - (( tries-- )) - if [ "$tries" -le 0 ]; then - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" - echo >&2 - exit 1 - fi - sleep 1 - done - - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - rootAuthDatabase='admin' - - "${mongo[@]}" "$rootAuthDatabase" <<-EOJS - db.createUser({ - user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), - pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), - roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] - }) - EOJS - fi - - export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - "${mongodHackedArgs[@]}" --shutdown - rm -f "$pidfile" - - echo - echo 'MongoDB init process complete; ready for start up.' - echo - fi - - mongodHackedArgs=("$@") - MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} - CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt - if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then - CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt - fi - if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then - CA="${MONGO_SSL_DIR}/ca.crt" - fi - if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem - _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" - if [ -f "${CA}" ]; then - _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" - fi - fi - MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} - if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem - _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" - if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then - _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" - fi - fi - - MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') - if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ]; then - _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" - - if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - tlsMode="none" - if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then - tlsMode='allowTLS' - elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then - tlsMode='requireTLS' - fi - - if [ "$tlsMode" != "none" ]; then - _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - fi - - _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" - if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" - fi - fi - _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" - - - _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" - fi - - set -- "${mongodHackedArgs[@]}" - - # MongoDB 3.6+ defaults to localhost-only binding - haveBindIp= - if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then - haveBindIp=1 - elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then - haveBindIp=1 - fi - if [ -z "$haveBindIp" ]; then - # so if no "--bind_ip" is specified, let's add "--bind_ip_all" - set -- "$@" --bind_ip_all - fi - - unset "${!MONGO_INITDB_@}" -fi - -rm -f "$jsonConfigFile" "$tempConfigFile" - -set -o xtrace +u - -exec "$@" \ No newline at end of file From f9629323da939074805360b895a64bb4f5f4e04e Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Thu, 15 Jan 2026 18:05:42 -0700 Subject: [PATCH 05/10] Remove mongodb 7.0-community --- .../Dockerfile | 79 --- percona-server-mongodb-7.0-community/LICENSE | 7 - .../mongodb.repo | 6 - .../ps-entry.sh | 462 ------------------ 4 files changed, 554 deletions(-) delete mode 100644 percona-server-mongodb-7.0-community/Dockerfile delete mode 100644 percona-server-mongodb-7.0-community/LICENSE delete mode 100644 percona-server-mongodb-7.0-community/mongodb.repo delete mode 100644 percona-server-mongodb-7.0-community/ps-entry.sh diff --git a/percona-server-mongodb-7.0-community/Dockerfile b/percona-server-mongodb-7.0-community/Dockerfile deleted file mode 100644 index 81d5420f..00000000 --- a/percona-server-mongodb-7.0-community/Dockerfile +++ /dev/null @@ -1,79 +0,0 @@ -FROM redhat/ubi9-minimal - -LABEL name="MongoDB Community Edition" \ - release="7.0" \ - vendor="MongoDB Inc." \ - summary="MongoDB Community Edition with Percona operator compatibility" \ - description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ - maintainer="Percona Development " -LABEL org.opencontainers.image.authors="info@percona.com" - -ENV PSMDB_VERSION 7.0.14 -ENV OS_VER el9 - -# Do not report during Docker image creation. -ARG PERCONA_TELEMETRY_DISABLE=1 - -COPY mongodb.repo /etc/yum.repos.d/mongodb.repo - -RUN set -ex; \ - microdnf -y update glibc; \ - microdnf -y update libgcrypt; \ - microdnf -y install \ - mongodb-org-${PSMDB_VERSION} \ - mongodb-org-database-${PSMDB_VERSION} \ - mongodb-org-server-${PSMDB_VERSION} \ - mongodb-mongosh \ - mongodb-org-mongos-${PSMDB_VERSION} \ - mongodb-org-tools-${PSMDB_VERSION} \ - numactl \ - numactl-libs \ - procps-ng \ - jq \ - tar \ - oniguruma \ - cyrus-sasl-gssapi \ - cyrus-sasl-plain \ - policycoreutils; \ - microdnf clean all; \ - rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ - chown -R 1001:0 /data/db - -# the numeric UID is needed for OpenShift -RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ - -c "Default Application User" mongodb; \ - chmod g+rwx /var/log/mongo; \ - chown :0 /var/log/mongo - -COPY LICENSE /licenses/LICENSE.Dockerfile -RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ - echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community - -ENV GOSU_VERSION=1.11 -RUN set -eux; \ - curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ - curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ - \ - export GNUPGHOME="$(mktemp -d)"; \ - gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ - gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ - rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ - \ - chmod +x /usr/bin/gosu; \ - curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE - -VOLUME ["/data/db"] - -RUN set -ex; \ - curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ - echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - - -COPY ps-entry.sh /entrypoint.sh - -ENTRYPOINT ["/entrypoint.sh"] - -EXPOSE 27017 - -USER 1001 - -CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-7.0-community/LICENSE b/percona-server-mongodb-7.0-community/LICENSE deleted file mode 100644 index 0ae7afb4..00000000 --- a/percona-server-mongodb-7.0-community/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -MongoDB Community Edition License - -This software is licensed under the Server Side Public License (SSPL) v1. -For more information, see: https://www.mongodb.com/licensing/server-side-public-license - -This Docker image contains MongoDB Community Edition binaries and is configured -for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-7.0-community/mongodb.repo b/percona-server-mongodb-7.0-community/mongodb.repo deleted file mode 100644 index c32d12f2..00000000 --- a/percona-server-mongodb-7.0-community/mongodb.repo +++ /dev/null @@ -1,6 +0,0 @@ -[mongodb-org-7.0] -name=MongoDB Repository -baseurl=https://repo.mongodb.com/yum/amazon/2023/mongodb-org/7.0/x86_64/ -gpgcheck=1 -enabled=1 -gpgkey=https://pgp.mongodb.com/server-7.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-7.0-community/ps-entry.sh b/percona-server-mongodb-7.0-community/ps-entry.sh deleted file mode 100644 index 89cb67af..00000000 --- a/percona-server-mongodb-7.0-community/ps-entry.sh +++ /dev/null @@ -1,462 +0,0 @@ -#!/bin/bash -set -Eeuo pipefail - -if [ "${1:0:1}" = '-' ]; then - set -- mongod "$@" -fi - -originalArgOne="$1" - -# allow the container to be started with `--user` -# all mongo* commands should be dropped to the correct user -if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then - if [ "$originalArgOne" = 'mongod' ]; then - if [ -d "/data/configdb" ]; then - find /data/configdb \! -user mongodb -exec chown mongodb '{}' + - fi - if [ -d "/data/db" ]; then - find /data/db \! -user mongodb -exec chown mongodb '{}' + - fi - fi - - # make sure we can write to stdout and stderr as "mongodb" - # (for our "initdb" code later; see "--logpath" below) - chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : - # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 - - exec gosu mongodb:1001 "$BASH_SOURCE" "$@" -fi - -# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. -# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux -if [[ "$originalArgOne" == mongo* ]]; then - numa='numactl --interleave=all' - if $numa true &> /dev/null; then - set -- $numa "$@" - fi -fi - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) -_mongod_hack_have_arg() { - local checkArg="$1"; shift - local arg - for arg; do - case "$arg" in - "$checkArg"|"$checkArg"=*) - return 0 - ;; - esac - done - return 1 -} -# _mongod_hack_get_arg_val '--some-arg' "$@" -_mongod_hack_get_arg_val() { - local checkArg="$1"; shift - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$checkArg") - echo "$1" - return 0 - ;; - "$checkArg"=*) - echo "${arg#$checkArg=}" - return 0 - ;; - esac - done - return 1 -} -declare -a mongodHackedArgs -# _mongod_hack_ensure_arg '--some-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg() { - local ensureArg="$1"; shift - mongodHackedArgs=( "$@" ) - if ! _mongod_hack_have_arg "$ensureArg" "$@"; then - mongodHackedArgs+=( "$ensureArg" ) - fi -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$ensureNoArg" ]; then - continue - fi - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg_val() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$ensureNoArg") - shift # also skip the value - continue - ;; - "$ensureNoArg"=*) - # value is already included - continue - ;; - esac - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg_val() { - local ensureArg="$1"; shift - local ensureVal="$1"; shift - _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" - mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) -} - -# required by mongodb 4.2 -# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg_save_val() { - local oldArg="$1"; shift - local newArg="$1"; shift - if ! _mongod_hack_have_arg "$oldArg" "$@"; then - return 0 - fi - local val="" - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$oldArg" ]; then - val="$1"; shift - continue - elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then - val=${BASH_REMATCH[1]} - continue - fi - mongodHackedArgs+=("$arg") - done - mongodHackedArgs+=("$newArg" "$val") -} - -# required by mongodb 4.2 -# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg() { - local oldArg="$1"; shift - local newArg="$1"; shift - if _mongod_hack_have_arg "$oldArg" "$@"; then - _mongod_hack_ensure_no_arg "$oldArg" "$@" - _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" - fi -} - -# _js_escape 'some "string" value' -_js_escape() { - jq --null-input --arg 'str' "$1" '$str' -} - -jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" -tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" -_parse_config() { - if [ -s "$tempConfigFile" ]; then - return 0 - fi - - local configPath - if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then - # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) - # see https://docs.mongodb.com/manual/reference/configuration-options/ - mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" - jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" - return 0 - fi - - return 1 -} -dbPath= -_dbPath() { - if [ -n "$dbPath" ]; then - echo "$dbPath" - return - fi - - if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then - if _parse_config "$@"; then - dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" - fi - fi - - : "${dbPath:=/data/db}" - - echo "$dbPath" -} - -if [ "$originalArgOne" = 'mongod' ]; then - file_env 'MONGO_INITDB_ROOT_USERNAME' - file_env 'MONGO_INITDB_ROOT_PASSWORD' - # pre-check a few factors to see if it's even worth bothering with initdb - shouldPerformInitdb= - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - # if we have a username/password, let's set "--auth" - _mongod_hack_ensure_arg '--auth' "$@" - set -- "${mongodHackedArgs[@]}" - shouldPerformInitdb='true' - elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - cat >&2 <<-'EOF' - - error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' - both must be specified for a user to be created - - EOF - exit 1 - fi - - if [ -z "$shouldPerformInitdb" ]; then - # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh|*.js) # this should match the set of files we check for below - shouldPerformInitdb="$f" - break - ;; - esac - done - fi - - # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) - if [ -n "$shouldPerformInitdb" ]; then - dbPath="$(_dbPath "$@")" - for path in \ - "$dbPath/WiredTiger" \ - "$dbPath/journal" \ - "$dbPath/local.0" \ - "$dbPath/storage.bson" \ - ; do - if [ -e "$path" ]; then - shouldPerformInitdb= - break - fi - done - fi - - if [ -n "$shouldPerformInitdb" ]; then - mongodHackedArgs=( "$@" ) - _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" - - # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) - # https://github.com/docker-library/mongo/issues/211 - _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" - fi - - # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" - tlsMode='disabled' - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferSSL' - fi - # 4.2 switched all configuration/flag names from "SSL" to "TLS" - if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - else - _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - - if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then - # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 - # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 - _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" - else - initdbLogPath="$(_dbPath "$@")/docker-initdb.log" - echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" - _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" - fi - _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" - - pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" - rm -f "$pidfile" - _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" - - "${mongodHackedArgs[@]}" --fork - - mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) - - # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) - # https://jira.mongodb.org/browse/SERVER-16292 - tries=30 - while true; do - if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then - # bail ASAP if "mongod" isn't even running - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" - echo >&2 - exit 1 - fi - if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then - # success! - break - fi - (( tries-- )) - if [ "$tries" -le 0 ]; then - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" - echo >&2 - exit 1 - fi - sleep 1 - done - - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - rootAuthDatabase='admin' - - "${mongo[@]}" "$rootAuthDatabase" <<-EOJS - db.createUser({ - user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), - pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), - roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] - }) - EOJS - fi - - export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - "${mongodHackedArgs[@]}" --shutdown - rm -f "$pidfile" - - echo - echo 'MongoDB init process complete; ready for start up.' - echo - fi - - mongodHackedArgs=("$@") - MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} - CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt - if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then - CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt - fi - if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then - CA="${MONGO_SSL_DIR}/ca.crt" - fi - if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem - _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" - if [ -f "${CA}" ]; then - _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" - fi - fi - MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} - if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem - _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" - if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then - _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" - fi - fi - - MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') - if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ]; then - _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" - - if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - tlsMode="none" - if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then - tlsMode='allowTLS' - elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then - tlsMode='requireTLS' - fi - - if [ "$tlsMode" != "none" ]; then - _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - fi - - _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" - if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" - fi - fi - _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" - - - _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" - fi - - set -- "${mongodHackedArgs[@]}" - - # MongoDB 3.6+ defaults to localhost-only binding - haveBindIp= - if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then - haveBindIp=1 - elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then - haveBindIp=1 - fi - if [ -z "$haveBindIp" ]; then - # so if no "--bind_ip" is specified, let's add "--bind_ip_all" - set -- "$@" --bind_ip_all - fi - - unset "${!MONGO_INITDB_@}" -fi - -rm -f "$jsonConfigFile" "$tempConfigFile" - -set -o xtrace +u - -exec "$@" \ No newline at end of file From 86fffa1d4c5fd544ab875f70c314268efb5cbd1c Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Thu, 15 Jan 2026 18:06:07 -0700 Subject: [PATCH 06/10] Remove mongodb 6.0-community --- .../Dockerfile | 79 --- percona-server-mongodb-6.0-community/LICENSE | 7 - .../mongodb.repo | 6 - .../ps-entry.sh | 462 ------------------ 4 files changed, 554 deletions(-) delete mode 100644 percona-server-mongodb-6.0-community/Dockerfile delete mode 100644 percona-server-mongodb-6.0-community/LICENSE delete mode 100644 percona-server-mongodb-6.0-community/mongodb.repo delete mode 100644 percona-server-mongodb-6.0-community/ps-entry.sh diff --git a/percona-server-mongodb-6.0-community/Dockerfile b/percona-server-mongodb-6.0-community/Dockerfile deleted file mode 100644 index a3f30f99..00000000 --- a/percona-server-mongodb-6.0-community/Dockerfile +++ /dev/null @@ -1,79 +0,0 @@ -FROM redhat/ubi9-minimal - -LABEL name="MongoDB Community Edition" \ - release="6.0" \ - vendor="MongoDB Inc." \ - summary="MongoDB Community Edition with Percona operator compatibility" \ - description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ - maintainer="Percona Development " -LABEL org.opencontainers.image.authors="info@percona.com" - -ENV PSMDB_VERSION 6.0.16 -ENV OS_VER el9 - -# Do not report during Docker image creation. -ARG PERCONA_TELEMETRY_DISABLE=1 - -COPY mongodb.repo /etc/yum.repos.d/mongodb.repo - -RUN set -ex; \ - microdnf -y update glibc; \ - microdnf -y update libgcrypt; \ - microdnf -y install \ - mongodb-org-${PSMDB_VERSION} \ - mongodb-org-database-${PSMDB_VERSION} \ - mongodb-org-server-${PSMDB_VERSION} \ - mongodb-mongosh \ - mongodb-org-mongos-${PSMDB_VERSION} \ - mongodb-org-tools-${PSMDB_VERSION} \ - numactl \ - numactl-libs \ - procps-ng \ - jq \ - tar \ - oniguruma \ - cyrus-sasl-gssapi \ - cyrus-sasl-plain \ - policycoreutils; \ - microdnf clean all; \ - rm -rf /var/cache/dnf /var/cache/yum /data/db && mkdir -p /data/db; \ - chown -R 1001:0 /data/db - -# the numeric UID is needed for OpenShift -RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ - -c "Default Application User" mongodb; \ - chmod g+rwx /var/log/mongo; \ - chown :0 /var/log/mongo - -COPY LICENSE /licenses/LICENSE.Dockerfile -RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ - echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community - -ENV GOSU_VERSION=1.11 -RUN set -eux; \ - curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ - curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ - \ - export GNUPGHOME="$(mktemp -d)"; \ - gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ - gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ - rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ - \ - chmod +x /usr/bin/gosu; \ - curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE - -VOLUME ["/data/db"] - -RUN set -ex; \ - curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ - echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - - -COPY ps-entry.sh /entrypoint.sh - -ENTRYPOINT ["/entrypoint.sh"] - -EXPOSE 27017 - -USER 1001 - -CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-6.0-community/LICENSE b/percona-server-mongodb-6.0-community/LICENSE deleted file mode 100644 index 0ae7afb4..00000000 --- a/percona-server-mongodb-6.0-community/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -MongoDB Community Edition License - -This software is licensed under the Server Side Public License (SSPL) v1. -For more information, see: https://www.mongodb.com/licensing/server-side-public-license - -This Docker image contains MongoDB Community Edition binaries and is configured -for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-6.0-community/mongodb.repo b/percona-server-mongodb-6.0-community/mongodb.repo deleted file mode 100644 index cb62000d..00000000 --- a/percona-server-mongodb-6.0-community/mongodb.repo +++ /dev/null @@ -1,6 +0,0 @@ -[mongodb-org-6.0] -name=MongoDB Repository -baseurl=https://repo.mongodb.com/yum/amazon/2023/mongodb-org/6.0/x86_64/ -gpgcheck=1 -enabled=1 -gpgkey=https://pgp.mongodb.com/server-6.0.asc \ No newline at end of file diff --git a/percona-server-mongodb-6.0-community/ps-entry.sh b/percona-server-mongodb-6.0-community/ps-entry.sh deleted file mode 100644 index 89cb67af..00000000 --- a/percona-server-mongodb-6.0-community/ps-entry.sh +++ /dev/null @@ -1,462 +0,0 @@ -#!/bin/bash -set -Eeuo pipefail - -if [ "${1:0:1}" = '-' ]; then - set -- mongod "$@" -fi - -originalArgOne="$1" - -# allow the container to be started with `--user` -# all mongo* commands should be dropped to the correct user -if [[ "$originalArgOne" == mongo* ]] && [ "$(id -u)" = '0' ]; then - if [ "$originalArgOne" = 'mongod' ]; then - if [ -d "/data/configdb" ]; then - find /data/configdb \! -user mongodb -exec chown mongodb '{}' + - fi - if [ -d "/data/db" ]; then - find /data/db \! -user mongodb -exec chown mongodb '{}' + - fi - fi - - # make sure we can write to stdout and stderr as "mongodb" - # (for our "initdb" code later; see "--logpath" below) - chown --dereference mongodb "/proc/$/fd/1" "/proc/$/fd/2" || : - # ignore errors thanks to https://github.com/docker-library/mongo/issues/149 - - exec gosu mongodb:1001 "$BASH_SOURCE" "$@" -fi - -# you should use numactl to start your mongod instances, including the config servers, mongos instances, and any clients. -# https://docs.mongodb.com/manual/administration/production-notes/#configuring-numa-on-linux -if [[ "$originalArgOne" == mongo* ]]; then - numa='numactl --interleave=all' - if $numa true &> /dev/null; then - set -- $numa "$@" - fi -fi - -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -# see https://github.com/docker-library/mongo/issues/147 (mongod is picky about duplicated arguments) -_mongod_hack_have_arg() { - local checkArg="$1"; shift - local arg - for arg; do - case "$arg" in - "$checkArg"|"$checkArg"=*) - return 0 - ;; - esac - done - return 1 -} -# _mongod_hack_get_arg_val '--some-arg' "$@" -_mongod_hack_get_arg_val() { - local checkArg="$1"; shift - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$checkArg") - echo "$1" - return 0 - ;; - "$checkArg"=*) - echo "${arg#$checkArg=}" - return 0 - ;; - esac - done - return 1 -} -declare -a mongodHackedArgs -# _mongod_hack_ensure_arg '--some-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg() { - local ensureArg="$1"; shift - mongodHackedArgs=( "$@" ) - if ! _mongod_hack_have_arg "$ensureArg" "$@"; then - mongodHackedArgs+=( "$ensureArg" ) - fi -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$ensureNoArg" ]; then - continue - fi - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_no_arg '--some-unwanted-arg' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_no_arg_val() { - local ensureNoArg="$1"; shift - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - case "$arg" in - "$ensureNoArg") - shift # also skip the value - continue - ;; - "$ensureNoArg"=*) - # value is already included - continue - ;; - esac - mongodHackedArgs+=( "$arg" ) - done -} -# _mongod_hack_ensure_arg_val '--some-arg' 'some-val' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_ensure_arg_val() { - local ensureArg="$1"; shift - local ensureVal="$1"; shift - _mongod_hack_ensure_no_arg_val "$ensureArg" "$@" - mongodHackedArgs+=( "$ensureArg" "$ensureVal" ) -} - -# required by mongodb 4.2 -# _mongod_hack_rename_arg_save_val '--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg_save_val() { - local oldArg="$1"; shift - local newArg="$1"; shift - if ! _mongod_hack_have_arg "$oldArg" "$@"; then - return 0 - fi - local val="" - mongodHackedArgs=() - while [ "$#" -gt 0 ]; do - local arg="$1"; shift - if [ "$arg" = "$oldArg" ]; then - val="$1"; shift - continue - elif [[ "$arg" =~ "$oldArg"=(.*) ]]; then - val=${BASH_REMATCH[1]} - continue - fi - mongodHackedArgs+=("$arg") - done - mongodHackedArgs+=("$newArg" "$val") -} - -# required by mongodb 4.2 -# _mongod_hack_rename_arg'--arg-to-rename' '--arg-to-rename-to' "$@" -# set -- "${mongodHackedArgs[@]}" -_mongod_hack_rename_arg() { - local oldArg="$1"; shift - local newArg="$1"; shift - if _mongod_hack_have_arg "$oldArg" "$@"; then - _mongod_hack_ensure_no_arg "$oldArg" "$@" - _mongod_hack_ensure_arg "$newArg" "${mongodHackedArgs[@]}" - fi -} - -# _js_escape 'some "string" value' -_js_escape() { - jq --null-input --arg 'str' "$1" '$str' -} - -jsonConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-config.json" -tempConfigFile="${TMPDIR:-/tmp}/docker-entrypoint-temp-config.json" -_parse_config() { - if [ -s "$tempConfigFile" ]; then - return 0 - fi - - local configPath - if configPath="$(_mongod_hack_get_arg_val --config "$@")"; then - # if --config is specified, parse it into a JSON file so we can remove a few problematic keys (especially SSL-related keys) - # see https://docs.mongodb.com/manual/reference/configuration-options/ - mongosh --norc --nodb --quiet --eval "load('/js-yaml.js'); JSON.stringify(jsyaml.load(fs.readFileSync($(_js_escape "$configPath"), 'utf8')))" > "$jsonConfigFile" - jq 'del(.systemLog, .processManagement, .net, .security)' "$jsonConfigFile" > "$tempConfigFile" - return 0 - fi - - return 1 -} -dbPath= -_dbPath() { - if [ -n "$dbPath" ]; then - echo "$dbPath" - return - fi - - if ! dbPath="$(_mongod_hack_get_arg_val --dbpath "$@")"; then - if _parse_config "$@"; then - dbPath="$(jq -r '.storage.dbPath // empty' "$jsonConfigFile")" - fi - fi - - : "${dbPath:=/data/db}" - - echo "$dbPath" -} - -if [ "$originalArgOne" = 'mongod' ]; then - file_env 'MONGO_INITDB_ROOT_USERNAME' - file_env 'MONGO_INITDB_ROOT_PASSWORD' - # pre-check a few factors to see if it's even worth bothering with initdb - shouldPerformInitdb= - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - # if we have a username/password, let's set "--auth" - _mongod_hack_ensure_arg '--auth' "$@" - set -- "${mongodHackedArgs[@]}" - shouldPerformInitdb='true' - elif [ "$MONGO_INITDB_ROOT_USERNAME" ] || [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - cat >&2 <<-'EOF' - - error: missing 'MONGO_INITDB_ROOT_USERNAME' or 'MONGO_INITDB_ROOT_PASSWORD' - both must be specified for a user to be created - - EOF - exit 1 - fi - - if [ -z "$shouldPerformInitdb" ]; then - # if we've got any /docker-entrypoint-initdb.d/* files to parse later, we should initdb - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh|*.js) # this should match the set of files we check for below - shouldPerformInitdb="$f" - break - ;; - esac - done - fi - - # check for a few known paths (to determine whether we've already initialized and should thus skip our initdb scripts) - if [ -n "$shouldPerformInitdb" ]; then - dbPath="$(_dbPath "$@")" - for path in \ - "$dbPath/WiredTiger" \ - "$dbPath/journal" \ - "$dbPath/local.0" \ - "$dbPath/storage.bson" \ - ; do - if [ -e "$path" ]; then - shouldPerformInitdb= - break - fi - done - fi - - if [ -n "$shouldPerformInitdb" ]; then - mongodHackedArgs=( "$@" ) - _mongod_hack_ensure_arg_val --bind_ip 127.0.0.1 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --port 27017 "${mongodHackedArgs[@]}" - _mongod_hack_ensure_no_arg --bind_ip_all "${mongodHackedArgs[@]}" - - # remove "--auth" and "--replSet" for our initial startup (see https://docs.mongodb.com/manual/tutorial/enable-authentication/#start-mongodb-without-access-control) - # https://github.com/docker-library/mongo/issues/211 - _mongod_hack_ensure_no_arg --auth "${mongodHackedArgs[@]}" - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - _mongod_hack_ensure_no_arg_val --replSet "${mongodHackedArgs[@]}" - fi - - # "BadValue: need sslPEMKeyFile when SSL is enabled" vs "BadValue: need to enable SSL via the sslMode flag when using SSL configuration parameters" - tlsMode='disabled' - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg '--sslPEMKeyFile' "${mongodHackedArgs[@]}"; then - tlsMode='preferSSL' - fi - # 4.2 switched all configuration/flag names from "SSL" to "TLS" - if [ "$tlsMode" = 'preferTLS' ] || mongod --help 2>&1 | grep -q -- ' --tlsMode '; then - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - else - _mongod_hack_ensure_arg_val --sslMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - - if stat "/proc/$/fd/1" > /dev/null && [ -w "/proc/$/fd/1" ]; then - # https://github.com/mongodb/mongo/blob/38c0eb538d0fd390c6cb9ce9ae9894153f6e8ef5/src/mongo/db/initialize_server_global_state.cpp#L237-L251 - # https://github.com/docker-library/mongo/issues/164#issuecomment-293965668 - _mongod_hack_ensure_arg_val --logpath "/proc/$/fd/1" "${mongodHackedArgs[@]}" - else - initdbLogPath="$(_dbPath "$@")/docker-initdb.log" - echo >&2 "warning: initdb logs cannot write to '/proc/$/fd/1', so they are in '$initdbLogPath' instead" - _mongod_hack_ensure_arg_val --logpath "$initdbLogPath" "${mongodHackedArgs[@]}" - fi - _mongod_hack_ensure_arg --logappend "${mongodHackedArgs[@]}" - - pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" - rm -f "$pidfile" - _mongod_hack_ensure_arg_val --pidfilepath "$pidfile" "${mongodHackedArgs[@]}" - - "${mongodHackedArgs[@]}" --fork - - mongo=( mongosh --host 127.0.0.1 --port 27017 --quiet ) - - # check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) - # https://jira.mongodb.org/browse/SERVER-16292 - tries=30 - while true; do - if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then - # bail ASAP if "mongod" isn't even running - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have stayed running -- perhaps it had an error?" - echo >&2 - exit 1 - fi - if "${mongo[@]}" 'admin' --eval 'quit(0)' &> /dev/null; then - # success! - break - fi - (( tries-- )) - if [ "$tries" -le 0 ]; then - echo >&2 - echo >&2 "error: $originalArgOne does not appear to have accepted connections quickly enough -- perhaps it had an error?" - echo >&2 - exit 1 - fi - sleep 1 - done - - if [ "$MONGO_INITDB_ROOT_USERNAME" ] && [ "$MONGO_INITDB_ROOT_PASSWORD" ]; then - rootAuthDatabase='admin' - - "${mongo[@]}" "$rootAuthDatabase" <<-EOJS - db.createUser({ - user: $(_js_escape "$MONGO_INITDB_ROOT_USERNAME"), - pwd: $(_js_escape "$MONGO_INITDB_ROOT_PASSWORD"), - roles: [ { role: 'root', db: $(_js_escape "$rootAuthDatabase") } ] - }) - EOJS - fi - - export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}" - - echo - for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.js) echo "$0: running $f"; "${mongo[@]}" "$MONGO_INITDB_DATABASE" "$f"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo - done - - "${mongodHackedArgs[@]}" --shutdown - rm -f "$pidfile" - - echo - echo 'MongoDB init process complete; ready for start up.' - echo - fi - - mongodHackedArgs=("$@") - MONGO_SSL_DIR=${MONGO_SSL_DIR:-/etc/mongodb-ssl} - CA=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt - if [ -f /var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt ]; then - CA=/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt - fi - if [ -f "${MONGO_SSL_DIR}/ca.crt" ]; then - CA="${MONGO_SSL_DIR}/ca.crt" - fi - if [ -f "${MONGO_SSL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_DIR}/tls.key" "${MONGO_SSL_DIR}/tls.crt" >/tmp/tls.pem - _mongod_hack_ensure_arg_val --sslPEMKeyFile /tmp/tls.pem "${mongodHackedArgs[@]}" - if [ -f "${CA}" ]; then - _mongod_hack_ensure_arg_val --sslCAFile "${CA}" "${mongodHackedArgs[@]}" - fi - fi - MONGO_SSL_INTERNAL_DIR=${MONGO_SSL_INTERNAL_DIR:-/etc/mongodb-ssl-internal} - if [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.key" ] && [ -f "${MONGO_SSL_INTERNAL_DIR}/tls.crt" ]; then - cat "${MONGO_SSL_INTERNAL_DIR}/tls.key" "${MONGO_SSL_INTERNAL_DIR}/tls.crt" >/tmp/tls-internal.pem - _mongod_hack_ensure_arg_val --sslClusterFile /tmp/tls-internal.pem "${mongodHackedArgs[@]}" - if [ -f "${MONGO_SSL_INTERNAL_DIR}/ca.crt" ]; then - _mongod_hack_ensure_arg_val --sslClusterCAFile "${MONGO_SSL_INTERNAL_DIR}/ca.crt" "${mongodHackedArgs[@]}" - fi - fi - - MONGODB_VERSION=$(mongod --version | head -1 | awk '{print $3}' | awk -F'.' '{print $1"."$2}') - if [ "$MONGODB_VERSION" == 'v4.2' ] || [ "$MONGODB_VERSION" == 'v4.4' ] || [ "$MONGODB_VERSION" == 'v5.0' ] || [ "$MONGODB_VERSION" == 'v6.0' ] || [ "$MONGODB_VERSION" == 'v7.0' ]; then - _mongod_hack_rename_arg_save_val --sslMode --tlsMode "${mongodHackedArgs[@]}" - - if _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - tlsMode="none" - if _mongod_hack_have_arg 'allowSSL' "${mongodHackedArgs[@]}"; then - tlsMode='allowTLS' - elif _mongod_hack_have_arg 'preferSSL' "${mongodHackedArgs[@]}"; then - tlsMode='preferTLS' - elif _mongod_hack_have_arg 'requireSSL' "${mongodHackedArgs[@]}"; then - tlsMode='requireTLS' - fi - - if [ "$tlsMode" != "none" ]; then - _mongod_hack_ensure_no_arg_val --tlsMode "${mongodHackedArgs[@]}" - _mongod_hack_ensure_arg_val --tlsMode "$tlsMode" "${mongodHackedArgs[@]}" - fi - fi - - _mongod_hack_rename_arg_save_val --sslPEMKeyFile --tlsCertificateKeyFile "${mongodHackedArgs[@]}" - if ! _mongod_hack_have_arg '--tlsMode' "${mongodHackedArgs[@]}"; then - if _mongod_hack_have_arg '--tlsCertificateKeyFile' "${mongodHackedArgs[@]}"; then - _mongod_hack_ensure_arg_val --tlsMode "preferTLS" "${mongodHackedArgs[@]}" - fi - fi - _mongod_hack_rename_arg '--sslAllowInvalidCertificates' '--tlsAllowInvalidCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowInvalidHostnames' '--tlsAllowInvalidHostnames' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslAllowConnectionsWithoutCertificates' '--tlsAllowConnectionsWithoutCertificates' "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg '--sslFIPSMode' '--tlsFIPSMode' "${mongodHackedArgs[@]}" - - - _mongod_hack_rename_arg_save_val --sslPEMKeyPassword --tlsCertificateKeyFilePassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterFile --tlsClusterFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCertificateSelector --tlsCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCertificateSelector --tlsClusterCertificateSelector "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterPassword --tlsClusterPassword "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCAFile --tlsCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslClusterCAFile --tlsClusterCAFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslCRLFile --tlsCRLFile "${mongodHackedArgs[@]}" - _mongod_hack_rename_arg_save_val --sslDisabledProtocols --tlsDisabledProtocols "${mongodHackedArgs[@]}" - fi - - set -- "${mongodHackedArgs[@]}" - - # MongoDB 3.6+ defaults to localhost-only binding - haveBindIp= - if _mongod_hack_have_arg --bind_ip "$@" || _mongod_hack_have_arg --bind_ip_all "$@"; then - haveBindIp=1 - elif _parse_config "$@" && jq --exit-status '.net.bindIp // .net.bindIpAll' "$jsonConfigFile" > /dev/null; then - haveBindIp=1 - fi - if [ -z "$haveBindIp" ]; then - # so if no "--bind_ip" is specified, let's add "--bind_ip_all" - set -- "$@" --bind_ip_all - fi - - unset "${!MONGO_INITDB_@}" -fi - -rm -f "$jsonConfigFile" "$tempConfigFile" - -set -o xtrace +u - -exec "$@" \ No newline at end of file From 29b23e8dd50c0c516a5a429320745abe1598be56 Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Fri, 16 Jan 2026 14:10:55 -0700 Subject: [PATCH 07/10] Add a build workflow and push to ghcr --- .github/workflows/build-mongodb-community.yml | 226 +++++++++++++++++ .../healthcheck.sh | 236 ++++++++++++++++++ .../ps-entry.sh | 33 +++ 3 files changed, 495 insertions(+) create mode 100644 .github/workflows/build-mongodb-community.yml create mode 100644 percona-server-mongodb-8.0-community/healthcheck.sh diff --git a/.github/workflows/build-mongodb-community.yml b/.github/workflows/build-mongodb-community.yml new file mode 100644 index 00000000..8cacfc35 --- /dev/null +++ b/.github/workflows/build-mongodb-community.yml @@ -0,0 +1,226 @@ +name: Build MongoDB Community Images + +on: + push: + branches: + - main + paths: + - 'percona-server-mongodb-8.0-community/**' + - '.github/workflows/build-mongodb-community.yml' + pull_request: + branches: + - main + paths: + - 'percona-server-mongodb-8.0-community/**' + - '.github/workflows/build-mongodb-community.yml' + release: + types: + - published + workflow_dispatch: + inputs: + push_images: + description: 'Push images to registry (true/false)' + required: false + default: 'false' + type: choice + options: + - 'true' + - 'false' + +env: + REGISTRY: ghcr.io + IMAGE_NAME: objectrocket/percona-docker/percona-server-mongodb-8.0-community + MONGODB_VERSION: 8.0.3 + +jobs: + build-and-push: + name: Build and Push MongoDB Community Images + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + id-token: write + + strategy: + fail-fast: false + matrix: + variant: + - name: standard + dockerfile: Dockerfile + suffix: '' + - name: k8s + dockerfile: Dockerfile.k8s + suffix: '-k8s' + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up QEMU for multi-architecture builds + uses: docker/setup-qemu-action@v3 + with: + platforms: linux/amd64,linux/arm64 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + driver-opts: | + image=moby/buildkit:latest + network=host + + - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + flavor: | + latest=auto + suffix=${{ matrix.variant.suffix }},onlatest=true + tags: | + type=raw,value=latest,enable={{is_default_branch}} + type=raw,value=${{ env.MONGODB_VERSION }} + type=raw,value=8.0 + type=semver,pattern={{version}},enable=${{ github.event_name == 'release' }} + type=semver,pattern={{major}}.{{minor}},enable=${{ github.event_name == 'release' }} + type=ref,event=pr + type=sha,format=short + labels: | + org.opencontainers.image.title=MongoDB Community Edition ${{ matrix.variant.name }} + org.opencontainers.image.description=Multi-architecture MongoDB Community Edition ${{ matrix.variant.name }} variant + org.opencontainers.image.version=${{ env.MONGODB_VERSION }} + org.opencontainers.image.vendor=ObjectRocket + org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} + org.opencontainers.image.revision=${{ github.sha }} + org.opencontainers.image.created=${{ github.event.head_commit.timestamp }} + org.opencontainers.image.licenses=SSPL-1.0 + io.objectrocket.mongodb.version=${{ env.MONGODB_VERSION }} + io.objectrocket.variant=${{ matrix.variant.name }} + + - name: Verify healthcheck.sh exists for k8s variant + if: matrix.variant.name == 'k8s' + run: | + if [ ! -f percona-server-mongodb-8.0-community/healthcheck.sh ]; then + echo "Error: healthcheck.sh not found for k8s variant" + exit 1 + fi + if [ ! -x percona-server-mongodb-8.0-community/healthcheck.sh ]; then + echo "Warning: healthcheck.sh is not executable, setting permissions" + chmod +x percona-server-mongodb-8.0-community/healthcheck.sh + fi + echo "✓ healthcheck.sh verified" + + - name: Build and push Docker image + id: build-push + uses: docker/build-push-action@v5 + with: + context: ./percona-server-mongodb-8.0-community + file: ./percona-server-mongodb-8.0-community/${{ matrix.variant.dockerfile }} + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' && (github.event_name == 'release' || github.ref == 'refs/heads/main' || github.event.inputs.push_images == 'true') }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha,scope=${{ matrix.variant.name }} + cache-to: type=gha,mode=max,scope=${{ matrix.variant.name }} + provenance: true + sbom: true + + - name: Generate build summary + run: | + echo "## Build Summary - ${{ matrix.variant.name }} variant" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Image:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Variant:** ${{ matrix.variant.name }}" >> $GITHUB_STEP_SUMMARY + echo "**Dockerfile:** ${{ matrix.variant.dockerfile }}" >> $GITHUB_STEP_SUMMARY + echo "**MongoDB Version:** ${{ env.MONGODB_VERSION }}" >> $GITHUB_STEP_SUMMARY + echo "**Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY + echo "**Digest:** \`${{ steps.build-push.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Tags" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY + echo "\`\`\`" >> $GITHUB_STEP_SUMMARY + + - name: Notify on failure + if: failure() + uses: actions/github-script@v7 + with: + script: | + const variant = '${{ matrix.variant.name }}'; + const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; + + if (context.eventName === 'pull_request') { + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `❌ MongoDB Community image build failed for **${variant}** variant.\n\n[View workflow run](${runUrl})` + }); + } + + core.setFailed(`Build failed for ${variant} variant`); + + verify-images: + name: Verify Published Images + needs: build-and-push + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' + + steps: + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Verify standard image + run: | + echo "Verifying standard image..." + docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.MONGODB_VERSION }} + docker inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.MONGODB_VERSION }} + echo "✓ Standard image verified" + + - name: Verify k8s image + run: | + echo "Verifying k8s image..." + docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.MONGODB_VERSION }}-k8s + docker inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.MONGODB_VERSION }}-k8s + + # Verify healthcheck.sh exists in k8s image + docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.MONGODB_VERSION }}-k8s test -x /healthcheck.sh + echo "✓ K8s image verified with healthcheck.sh" + + - name: Verify multi-architecture support + run: | + echo "Verifying multi-architecture manifests..." + docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.MONGODB_VERSION }} + docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.MONGODB_VERSION }}-k8s + echo "✓ Multi-architecture support verified" + + - name: Generate verification summary + run: | + echo "## Image Verification Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "✅ All images verified successfully" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "**Registry:** \`${{ env.REGISTRY }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Repository:** \`${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY + echo "**Version:** ${{ env.MONGODB_VERSION }}" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Available Images" >> $GITHUB_STEP_SUMMARY + echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.MONGODB_VERSION }}\`" >> $GITHUB_STEP_SUMMARY + echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.MONGODB_VERSION }}-k8s\`" >> $GITHUB_STEP_SUMMARY + echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:8.0\`" >> $GITHUB_STEP_SUMMARY + echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:8.0-k8s\`" >> $GITHUB_STEP_SUMMARY + echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest\`" >> $GITHUB_STEP_SUMMARY + echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-k8s\`" >> $GITHUB_STEP_SUMMARY diff --git a/percona-server-mongodb-8.0-community/healthcheck.sh b/percona-server-mongodb-8.0-community/healthcheck.sh new file mode 100644 index 00000000..63edfa77 --- /dev/null +++ b/percona-server-mongodb-8.0-community/healthcheck.sh @@ -0,0 +1,236 @@ +#!/bin/bash +# MongoDB Health Check Script for Kubernetes + +set -euo pipefail + +# Configuration +MONGODB_HOST="${MONGODB_HOST:-localhost}" +MONGODB_PORT="${MONGODB_PORT:-27017}" +MONGODB_DATABASE="${MONGODB_DATABASE:-admin}" +TIMEOUT="${HEALTH_CHECK_TIMEOUT:-10}" +MAX_RETRIES="${HEALTH_CHECK_RETRIES:-3}" + +# Logging function +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] HEALTHCHECK: $*" >&2 +} + +# Function to check if MongoDB is accepting connections +check_connection() { + local retry=0 + while [ $retry -lt $MAX_RETRIES ]; do + if timeout $TIMEOUT mongosh --host "$MONGODB_HOST" --port "$MONGODB_PORT" --quiet --eval "db.adminCommand('ping')" >/dev/null 2>&1; then + return 0 + fi + retry=$((retry + 1)) + log "Connection attempt $retry failed, retrying..." + sleep 1 + done + return 1 +} + +# Function to check MongoDB server status +check_server_status() { + local status_output + status_output=$(timeout $TIMEOUT mongosh --host "$MONGODB_HOST" --port "$MONGODB_PORT" --quiet --eval " + try { + var status = db.adminCommand('serverStatus'); + if (status.ok === 1) { + print('OK'); + } else { + print('ERROR: Server status not OK'); + } + } catch (e) { + print('ERROR: ' + e.message); + } + " 2>/dev/null) + + if [[ "$status_output" == "OK" ]]; then + return 0 + else + log "Server status check failed: $status_output" + return 1 + fi +} + +# Function to check if MongoDB is ready for read/write operations +check_readiness() { + local readiness_output + readiness_output=$(timeout $TIMEOUT mongosh --host "$MONGODB_HOST" --port "$MONGODB_PORT" --quiet --eval " + try { + // Check if we can perform basic operations + db.healthcheck.insertOne({timestamp: new Date(), check: 'readiness'}); + db.healthcheck.findOne({check: 'readiness'}); + db.healthcheck.deleteMany({check: 'readiness'}); + print('READY'); + } catch (e) { + print('NOT_READY: ' + e.message); + } + " 2>/dev/null) + + if [[ "$readiness_output" == "READY" ]]; then + return 0 + else + log "Readiness check failed: $readiness_output" + return 1 + fi +} + +# Function to check replica set status (if applicable) +check_replica_set() { + local rs_output + rs_output=$(timeout $TIMEOUT mongosh --host "$MONGODB_HOST" --port "$MONGODB_PORT" --quiet --eval " + try { + var status = rs.status(); + if (status.ok === 1) { + var myState = status.members.find(m => m.self === true); + if (myState && (myState.state === 1 || myState.state === 2)) { + print('RS_OK'); + } else { + print('RS_NOT_READY: State ' + (myState ? myState.state : 'unknown')); + } + } else { + print('RS_ERROR: ' + status.errmsg); + } + } catch (e) { + // Not a replica set or not initialized yet + print('RS_NOT_CONFIGURED'); + } + " 2>/dev/null) + + case "$rs_output" in + "RS_OK") + log "Replica set status: OK" + return 0 + ;; + "RS_NOT_CONFIGURED") + log "Replica set not configured (standalone mode)" + return 0 + ;; + *) + log "Replica set check failed: $rs_output" + return 1 + ;; + esac +} + +# Function to check disk space +check_disk_space() { + local data_dir="${MONGODB_DATA_DIR:-/data/db}" + local log_dir="${MONGODB_LOG_DIR:-/var/log/mongodb}" + local min_free_percent="${MIN_FREE_DISK_PERCENT:-10}" + + for dir in "$data_dir" "$log_dir"; do + if [[ -d "$dir" ]]; then + local usage + usage=$(df "$dir" | awk 'NR==2 {print $5}' | sed 's/%//') + local free_percent=$((100 - usage)) + + if [[ $free_percent -lt $min_free_percent ]]; then + log "Disk space warning: $dir has only $free_percent% free (minimum: $min_free_percent%)" + return 1 + fi + fi + done + return 0 +} + +# Function to check process health +check_process_health() { + # Check if mongod process is running + if ! pgrep -f mongod >/dev/null 2>&1; then + log "MongoDB process not found" + return 1 + fi + + # Check if process is responsive (not in uninterruptible sleep) + local mongod_pid + mongod_pid=$(pgrep -f mongod | head -1) + if [[ -n "$mongod_pid" ]]; then + local process_state + process_state=$(ps -o state= -p "$mongod_pid" 2>/dev/null | tr -d ' ') + if [[ "$process_state" == "D" ]]; then + log "MongoDB process is in uninterruptible sleep state" + return 1 + fi + fi + + return 0 +} + +# Main health check function +main() { + local exit_code=0 + local check_type="${1:-full}" + + log "Starting health check (type: $check_type)" + + # Always check process health first + if ! check_process_health; then + log "Process health check failed" + exit_code=1 + fi + + # Check MongoDB connection + if ! check_connection; then + log "Connection check failed" + exit_code=1 + fi + + # For full health checks, perform additional tests + if [[ "$check_type" == "full" ]]; then + # Check server status + if ! check_server_status; then + log "Server status check failed" + exit_code=1 + fi + + # Check readiness for operations + if ! check_readiness; then + log "Readiness check failed" + exit_code=1 + fi + + # Check replica set status if applicable + if ! check_replica_set; then + log "Replica set check failed" + exit_code=1 + fi + + # Check disk space + if ! check_disk_space; then + log "Disk space check failed" + exit_code=1 + fi + fi + + if [[ $exit_code -eq 0 ]]; then + log "Health check passed" + else + log "Health check failed" + fi + + exit $exit_code +} + +# Handle different invocation modes +case "${1:-full}" in + "liveness"|"live") + # Liveness probe - basic connection check + main "basic" + ;; + "readiness"|"ready") + # Readiness probe - full functionality check + main "full" + ;; + "startup") + # Startup probe - basic connection with retries + MAX_RETRIES=10 + TIMEOUT=30 + main "basic" + ;; + *) + # Default full health check + main "full" + ;; +esac diff --git a/percona-server-mongodb-8.0-community/ps-entry.sh b/percona-server-mongodb-8.0-community/ps-entry.sh index c82289f7..735468ae 100644 --- a/percona-server-mongodb-8.0-community/ps-entry.sh +++ b/percona-server-mongodb-8.0-community/ps-entry.sh @@ -270,8 +270,41 @@ start_mongodb() { fi } +# Function to check if command is MongoDB-related +is_mongodb_command() { + local cmd="$1" + + # List of MongoDB-related commands + case "$cmd" in + mongod|mongos|mongo|mongosh) + return 0 + ;; + *) + return 1 + ;; + esac +} + # Main execution function main() { + # Check if we should run MongoDB initialization or just exec the command + local first_arg="${1:-mongod}" + + # If the first argument is not a MongoDB command, just exec it directly + # This allows for command overrides like: docker run image echo "hello" + if ! is_mongodb_command "$first_arg"; then + log "Non-MongoDB command detected: $first_arg" + log "Executing command directly without MongoDB initialization" + + # If running as root, switch to mongodb user for consistency + if [[ "$(id -u)" = '0' ]]; then + exec gosu "$MONGODB_UID:$MONGODB_GID" "$@" + else + exec "$@" + fi + fi + + # MongoDB command detected, proceed with full initialization log "Starting MongoDB entrypoint for Kubernetes..." log "Pod: ${K8S_POD_NAME:-unknown}, Namespace: ${K8S_NAMESPACE:-unknown}" From 5f8e462f82364d67ca4a2704ef5ed3f89d49eb04 Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Tue, 20 Jan 2026 12:11:20 -0700 Subject: [PATCH 08/10] Bump version to see if trivy passes --- percona-server-mongodb-8.0-community/Dockerfile | 2 +- percona-server-mongodb-8.0-community/Dockerfile.k8s | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/percona-server-mongodb-8.0-community/Dockerfile b/percona-server-mongodb-8.0-community/Dockerfile index 50a73b21..f828fbf4 100644 --- a/percona-server-mongodb-8.0-community/Dockerfile +++ b/percona-server-mongodb-8.0-community/Dockerfile @@ -8,7 +8,7 @@ LABEL name="MongoDB Community Edition" \ maintainer="Percona Development " LABEL org.opencontainers.image.authors="info@percona.com" -ENV PSMDB_VERSION=8.0.3 +ENV PSMDB_VERSION=8.0.17 ENV OS_VER=el9 # Do not report during Docker image creation. diff --git a/percona-server-mongodb-8.0-community/Dockerfile.k8s b/percona-server-mongodb-8.0-community/Dockerfile.k8s index 01b5e8ea..5df30e56 100644 --- a/percona-server-mongodb-8.0-community/Dockerfile.k8s +++ b/percona-server-mongodb-8.0-community/Dockerfile.k8s @@ -10,7 +10,7 @@ FROM --platform=${TARGETPLATFORM} redhat/ubi9-minimal # Kubernetes and OpenShift compatibility labels LABEL name="MongoDB Community Edition for Kubernetes" \ release="8.0" \ - version="8.0.3" \ + version="8.0.17" \ vendor="MongoDB Inc." \ summary="MongoDB Community Edition optimized for Kubernetes with Percona operator compatibility" \ description="Multi-architecture MongoDB Community Edition container optimized for Kubernetes deployments. Includes enhanced security, health checks, and operator integration." \ @@ -22,7 +22,7 @@ LABEL name="MongoDB Community Edition for Kubernetes" \ LABEL org.opencontainers.image.title="MongoDB Community Edition for Kubernetes" \ org.opencontainers.image.description="Multi-architecture MongoDB Community Edition optimized for Kubernetes" \ - org.opencontainers.image.version="8.0.3" \ + org.opencontainers.image.version="8.0.17" \ org.opencontainers.image.authors="info@percona.com" \ org.opencontainers.image.vendor="Percona" \ org.opencontainers.image.licenses="SSPL-1.0" \ @@ -30,7 +30,7 @@ LABEL org.opencontainers.image.title="MongoDB Community Edition for Kubernetes" org.opencontainers.image.documentation="https://docs.percona.com/" # Environment variables for MongoDB and Kubernetes -ENV PSMDB_VERSION=8.0.3 \ +ENV PSMDB_VERSION=8.0.17 \ OS_VER=el9 \ MONGODB_VERSION=8.0 \ GOSU_VERSION=1.17 \ From aa6ae73a16d5c3886710f580fc45fb48ae6c2cc0 Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Tue, 20 Jan 2026 12:46:30 -0700 Subject: [PATCH 09/10] Bump to 8.2 for 8.0 --- percona-server-mongodb-8.0-community/Dockerfile | 2 +- percona-server-mongodb-8.0-community/Dockerfile.k8s | 12 ++++++------ percona-server-mongodb-8.0-community/mongodb.repo | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/percona-server-mongodb-8.0-community/Dockerfile b/percona-server-mongodb-8.0-community/Dockerfile index f828fbf4..67a87d42 100644 --- a/percona-server-mongodb-8.0-community/Dockerfile +++ b/percona-server-mongodb-8.0-community/Dockerfile @@ -8,7 +8,7 @@ LABEL name="MongoDB Community Edition" \ maintainer="Percona Development " LABEL org.opencontainers.image.authors="info@percona.com" -ENV PSMDB_VERSION=8.0.17 +ENV PSMDB_VERSION=8.2.3 ENV OS_VER=el9 # Do not report during Docker image creation. diff --git a/percona-server-mongodb-8.0-community/Dockerfile.k8s b/percona-server-mongodb-8.0-community/Dockerfile.k8s index 5df30e56..16924ab2 100644 --- a/percona-server-mongodb-8.0-community/Dockerfile.k8s +++ b/percona-server-mongodb-8.0-community/Dockerfile.k8s @@ -9,20 +9,20 @@ FROM --platform=${TARGETPLATFORM} redhat/ubi9-minimal # Kubernetes and OpenShift compatibility labels LABEL name="MongoDB Community Edition for Kubernetes" \ - release="8.0" \ - version="8.0.17" \ + release="8.2" \ + version="8.2.3" \ vendor="MongoDB Inc." \ summary="MongoDB Community Edition optimized for Kubernetes with Percona operator compatibility" \ description="Multi-architecture MongoDB Community Edition container optimized for Kubernetes deployments. Includes enhanced security, health checks, and operator integration." \ maintainer="Percona Development " \ io.k8s.description="MongoDB Community Edition for Kubernetes" \ - io.k8s.display-name="MongoDB Community 8.0" \ + io.k8s.display-name="MongoDB Community 8.2" \ io.openshift.expose-services="27017:mongodb" \ io.openshift.tags="database,mongodb,nosql" LABEL org.opencontainers.image.title="MongoDB Community Edition for Kubernetes" \ org.opencontainers.image.description="Multi-architecture MongoDB Community Edition optimized for Kubernetes" \ - org.opencontainers.image.version="8.0.17" \ + org.opencontainers.image.version="8.2.3" \ org.opencontainers.image.authors="info@percona.com" \ org.opencontainers.image.vendor="Percona" \ org.opencontainers.image.licenses="SSPL-1.0" \ @@ -30,9 +30,9 @@ LABEL org.opencontainers.image.title="MongoDB Community Edition for Kubernetes" org.opencontainers.image.documentation="https://docs.percona.com/" # Environment variables for MongoDB and Kubernetes -ENV PSMDB_VERSION=8.0.17 \ +ENV PSMDB_VERSION=8.2.3 \ OS_VER=el9 \ - MONGODB_VERSION=8.0 \ + MONGODB_VERSION=8.2 \ GOSU_VERSION=1.17 \ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin diff --git a/percona-server-mongodb-8.0-community/mongodb.repo b/percona-server-mongodb-8.0-community/mongodb.repo index 235f6f68..8ea5273e 100644 --- a/percona-server-mongodb-8.0-community/mongodb.repo +++ b/percona-server-mongodb-8.0-community/mongodb.repo @@ -1,6 +1,6 @@ -[mongodb-org-8.0] +[mongodb-org-8.2] name=MongoDB Repository -baseurl=https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.0/$basearch/ +baseurl=https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.2/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/server-8.0.asc From 2adc2727ea2c21bc81d82447b991e81edc0f10c8 Mon Sep 17 00:00:00 2001 From: Kevin Klaes Date: Tue, 20 Jan 2026 13:21:16 -0700 Subject: [PATCH 10/10] Add 8.0.17 back and keep 8.2.3 --- .../.trivyignore | 96 +++++ .../Dockerfile | 2 +- .../Dockerfile.k8s | 12 +- .../k8s-examples/mongodb-deployment.yaml | 231 ++++++++++++ .../k8s-examples/mongodb-simple.yaml | 158 +++++++++ .../mongodb.repo | 4 +- .../.trivyignore | 45 +++ .../Dockerfile | 78 ++++ .../Dockerfile.k8s | 198 +++++++++++ percona-server-mongodb-8.2-community/LICENSE | 7 + .../healthcheck.sh | 236 +++++++++++++ .../k8s-examples/mongodb-deployment.yaml | 231 ++++++++++++ .../k8s-examples/mongodb-simple.yaml | 158 +++++++++ .../mongodb.repo | 10 + .../ps-entry.sh | 332 ++++++++++++++++++ 15 files changed, 1789 insertions(+), 9 deletions(-) create mode 100644 percona-server-mongodb-8.0-community/.trivyignore create mode 100644 percona-server-mongodb-8.0-community/k8s-examples/mongodb-deployment.yaml create mode 100644 percona-server-mongodb-8.0-community/k8s-examples/mongodb-simple.yaml create mode 100644 percona-server-mongodb-8.2-community/.trivyignore create mode 100644 percona-server-mongodb-8.2-community/Dockerfile create mode 100644 percona-server-mongodb-8.2-community/Dockerfile.k8s create mode 100644 percona-server-mongodb-8.2-community/LICENSE create mode 100644 percona-server-mongodb-8.2-community/healthcheck.sh create mode 100644 percona-server-mongodb-8.2-community/k8s-examples/mongodb-deployment.yaml create mode 100644 percona-server-mongodb-8.2-community/k8s-examples/mongodb-simple.yaml create mode 100644 percona-server-mongodb-8.2-community/mongodb.repo create mode 100644 percona-server-mongodb-8.2-community/ps-entry.sh diff --git a/percona-server-mongodb-8.0-community/.trivyignore b/percona-server-mongodb-8.0-community/.trivyignore new file mode 100644 index 00000000..da2041ff --- /dev/null +++ b/percona-server-mongodb-8.0-community/.trivyignore @@ -0,0 +1,96 @@ +# Trivy Ignore File for MongoDB Community Edition 8.0 +# +# These vulnerabilities are in the MongoDB database tools (Go binaries) +# provided by MongoDB Inc. in the mongodb-org-tools package. +# +# MongoDB 8.0.17 includes older database tools that are still compiled +# with Go 1.24.0, which has known vulnerabilities. These are upstream +# issues that require MongoDB to recompile the tools with a patched +# Go version (1.24.11+ or 1.25.5+). +# +# Affected binaries: +# - bsondump, mongodump, mongoexport, mongofiles +# - mongoimport, mongorestore, mongostat, mongotop +# +# MongoDB Version: 8.0.17 +# Database Tools Version: Bundled with 8.0.17 +# Go Version (in tools): 1.24.0 +# +# Status: Waiting for MongoDB to recompile tools with Go 1.24.11+ or 1.25.5+ +# Last Updated: 2026-01-20 +# Review Date: Check monthly for MongoDB updates + +# CVE-2025-22874: crypto/x509 - ExtKeyUsageAny disables policy validation +# Severity: HIGH +# Fixed in: Go 1.24.4+ +# Component: stdlib in MongoDB database tools +CVE-2025-22874 + +# CVE-2025-47907: database/sql - Postgres Scan Race Condition +# Severity: HIGH +# Fixed in: Go 1.23.12, 1.24.6+ +# Component: stdlib in MongoDB database tools +CVE-2025-47907 + +# CVE-2025-58183: archive/tar - Unbounded allocation when parsing GNU sparse map +# Severity: HIGH +# Fixed in: Go 1.24.8, 1.25.2+ +# Component: stdlib in MongoDB database tools +CVE-2025-58183 + +# CVE-2025-61729: crypto/x509 - Denial of Service due to excessive resource consumption +# Severity: HIGH +# Fixed in: Go 1.24.11, 1.25.5+ +# Component: stdlib in MongoDB database tools +CVE-2025-61729 + +# ============================================================================ +# GOSU VULNERABILITIES (Kubernetes image only) +# ============================================================================ +# These vulnerabilities are in gosu 1.17, which is compiled with Go 1.18.2. +# Gosu is used in the Kubernetes image for privilege dropping. +# +# Gosu Version: 1.17 +# Go Version (in gosu): 1.18.2 +# +# Status: These are old CVEs in an older version of gosu. Consider upgrading +# to a newer gosu version or accepting the risk for this use case. +# Last Updated: 2026-01-20 + +# Multiple CVEs in gosu (Go 1.18.2) - CRITICAL severity +CVE-2023-24538 +CVE-2023-24540 +CVE-2024-24790 + +# Multiple CVEs in gosu (Go 1.18.2) - HIGH severity +CVE-2022-27664 +CVE-2022-28131 +CVE-2022-2879 +CVE-2022-2880 +CVE-2022-29804 +CVE-2022-30580 +CVE-2022-30630 +CVE-2022-30631 +CVE-2022-30632 +CVE-2022-30633 +CVE-2022-30634 +CVE-2022-30635 +CVE-2022-32189 +CVE-2022-41715 +CVE-2022-41716 +CVE-2022-41720 +CVE-2022-41722 +CVE-2022-41723 +CVE-2022-41724 +CVE-2022-41725 +CVE-2023-24534 +CVE-2023-24536 +CVE-2023-24537 +CVE-2023-24539 +CVE-2023-29400 +CVE-2023-29403 +CVE-2023-39325 +CVE-2023-45283 +CVE-2023-45287 +CVE-2023-45288 +CVE-2024-34156 diff --git a/percona-server-mongodb-8.0-community/Dockerfile b/percona-server-mongodb-8.0-community/Dockerfile index 67a87d42..f828fbf4 100644 --- a/percona-server-mongodb-8.0-community/Dockerfile +++ b/percona-server-mongodb-8.0-community/Dockerfile @@ -8,7 +8,7 @@ LABEL name="MongoDB Community Edition" \ maintainer="Percona Development " LABEL org.opencontainers.image.authors="info@percona.com" -ENV PSMDB_VERSION=8.2.3 +ENV PSMDB_VERSION=8.0.17 ENV OS_VER=el9 # Do not report during Docker image creation. diff --git a/percona-server-mongodb-8.0-community/Dockerfile.k8s b/percona-server-mongodb-8.0-community/Dockerfile.k8s index 16924ab2..5df30e56 100644 --- a/percona-server-mongodb-8.0-community/Dockerfile.k8s +++ b/percona-server-mongodb-8.0-community/Dockerfile.k8s @@ -9,20 +9,20 @@ FROM --platform=${TARGETPLATFORM} redhat/ubi9-minimal # Kubernetes and OpenShift compatibility labels LABEL name="MongoDB Community Edition for Kubernetes" \ - release="8.2" \ - version="8.2.3" \ + release="8.0" \ + version="8.0.17" \ vendor="MongoDB Inc." \ summary="MongoDB Community Edition optimized for Kubernetes with Percona operator compatibility" \ description="Multi-architecture MongoDB Community Edition container optimized for Kubernetes deployments. Includes enhanced security, health checks, and operator integration." \ maintainer="Percona Development " \ io.k8s.description="MongoDB Community Edition for Kubernetes" \ - io.k8s.display-name="MongoDB Community 8.2" \ + io.k8s.display-name="MongoDB Community 8.0" \ io.openshift.expose-services="27017:mongodb" \ io.openshift.tags="database,mongodb,nosql" LABEL org.opencontainers.image.title="MongoDB Community Edition for Kubernetes" \ org.opencontainers.image.description="Multi-architecture MongoDB Community Edition optimized for Kubernetes" \ - org.opencontainers.image.version="8.2.3" \ + org.opencontainers.image.version="8.0.17" \ org.opencontainers.image.authors="info@percona.com" \ org.opencontainers.image.vendor="Percona" \ org.opencontainers.image.licenses="SSPL-1.0" \ @@ -30,9 +30,9 @@ LABEL org.opencontainers.image.title="MongoDB Community Edition for Kubernetes" org.opencontainers.image.documentation="https://docs.percona.com/" # Environment variables for MongoDB and Kubernetes -ENV PSMDB_VERSION=8.2.3 \ +ENV PSMDB_VERSION=8.0.17 \ OS_VER=el9 \ - MONGODB_VERSION=8.2 \ + MONGODB_VERSION=8.0 \ GOSU_VERSION=1.17 \ PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin diff --git a/percona-server-mongodb-8.0-community/k8s-examples/mongodb-deployment.yaml b/percona-server-mongodb-8.0-community/k8s-examples/mongodb-deployment.yaml new file mode 100644 index 00000000..c4ab31bb --- /dev/null +++ b/percona-server-mongodb-8.0-community/k8s-examples/mongodb-deployment.yaml @@ -0,0 +1,231 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: mongodb + labels: + name: mongodb +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mongodb-config + namespace: mongodb +data: + mongod.conf: | + # MongoDB configuration for Kubernetes + storage: + dbPath: /data/db + journal: + enabled: true + wiredTiger: + engineConfig: + cacheSizeGB: 1.0 + + systemLog: + destination: file + logAppend: true + path: /var/log/mongodb/mongod.log + logRotate: reopen + verbosity: 1 + + net: + port: 27017 + bindIpAll: true + maxIncomingConnections: 1000 + + processManagement: + timeZoneInfo: /usr/share/zoneinfo + + security: + authorization: enabled + + replication: + replSetName: rs0 + + operationProfiling: + slowOpThresholdMs: 100 + mode: slowOp +--- +apiVersion: v1 +kind: Secret +metadata: + name: mongodb-secret + namespace: mongodb +type: Opaque +data: + # echo -n 'admin' | base64 + username: YWRtaW4= + # echo -n 'SecurePassword123!' | base64 + password: U2VjdXJlUGFzc3dvcmQxMjMh +--- +apiVersion: v1 +kind: Service +metadata: + name: mongodb-service + namespace: mongodb + labels: + app: mongodb +spec: + type: ClusterIP + ports: + - port: 27017 + targetPort: 27017 + protocol: TCP + name: mongodb + selector: + app: mongodb +--- +apiVersion: v1 +kind: Service +metadata: + name: mongodb-headless + namespace: mongodb + labels: + app: mongodb +spec: + type: ClusterIP + clusterIP: None + ports: + - port: 27017 + targetPort: 27017 + protocol: TCP + name: mongodb + selector: + app: mongodb +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mongodb + namespace: mongodb + labels: + app: mongodb +spec: + serviceName: mongodb-headless + replicas: 3 + selector: + matchLabels: + app: mongodb + template: + metadata: + labels: + app: mongodb + spec: + securityContext: + runAsUser: 1001 + runAsGroup: 0 + fsGroup: 0 + runAsNonRoot: true + containers: + - name: mongodb + image: percona/percona-server-mongodb:8.0-community-k8s + imagePullPolicy: IfNotPresent + ports: + - containerPort: 27017 + name: mongodb + protocol: TCP + env: + - name: MONGO_INITDB_ROOT_USERNAME_FILE + value: /etc/mongodb-secret/username + - name: MONGO_INITDB_ROOT_PASSWORD_FILE + value: /etc/mongodb-secret/password + - name: MONGO_INITDB_DATABASE + value: admin + - name: REPLICA_SET_NAME + value: rs0 + - name: K8S_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: K8S_SERVICE_NAME + value: mongodb-headless + - name: MONGODB_DATA_DIR + value: /data/db + - name: MONGODB_LOG_DIR + value: /var/log/mongodb + - name: MONGODB_CONFIG_DIR + value: /etc/mongodb + resources: + requests: + memory: "512Mi" + cpu: "250m" + limits: + memory: "2Gi" + cpu: "1000m" + volumeMounts: + - name: mongodb-data + mountPath: /data/db + - name: mongodb-logs + mountPath: /var/log/mongodb + - name: mongodb-config + mountPath: /etc/mongodb/mongod.conf.template + subPath: mongod.conf + readOnly: true + - name: mongodb-secret + mountPath: /etc/mongodb-secret + readOnly: true + livenessProbe: + exec: + command: + - /healthcheck.sh + - liveness + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + readinessProbe: + exec: + command: + - /healthcheck.sh + - readiness + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + successThreshold: 1 + startupProbe: + exec: + command: + - /healthcheck.sh + - startup + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 30 + failureThreshold: 30 + successThreshold: 1 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 1001 + runAsGroup: 0 + capabilities: + drop: + - ALL + volumes: + - name: mongodb-config + configMap: + name: mongodb-config + defaultMode: 0644 + - name: mongodb-secret + secret: + secretName: mongodb-secret + defaultMode: 0400 + - name: mongodb-logs + emptyDir: {} + terminationGracePeriodSeconds: 30 + restartPolicy: Always + volumeClaimTemplates: + - metadata: + name: mongodb-data + spec: + accessModes: ["ReadWriteOnce"] + storageClassName: "standard" + resources: + requests: + storage: 10Gi \ No newline at end of file diff --git a/percona-server-mongodb-8.0-community/k8s-examples/mongodb-simple.yaml b/percona-server-mongodb-8.0-community/k8s-examples/mongodb-simple.yaml new file mode 100644 index 00000000..4ab29401 --- /dev/null +++ b/percona-server-mongodb-8.0-community/k8s-examples/mongodb-simple.yaml @@ -0,0 +1,158 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: mongodb-simple +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mongodb-config + namespace: mongodb-simple +data: + mongod.conf: | + # Simple MongoDB configuration for Kubernetes + storage: + dbPath: /data/db + journal: + enabled: true + + systemLog: + destination: file + logAppend: true + path: /var/log/mongodb/mongod.log + + net: + port: 27017 + bindIpAll: true + + processManagement: + timeZoneInfo: /usr/share/zoneinfo + + security: + authorization: disabled +--- +apiVersion: v1 +kind: Service +metadata: + name: mongodb + namespace: mongodb-simple + labels: + app: mongodb +spec: + type: ClusterIP + ports: + - port: 27017 + targetPort: 27017 + protocol: TCP + name: mongodb + selector: + app: mongodb +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mongodb + namespace: mongodb-simple + labels: + app: mongodb +spec: + replicas: 1 + selector: + matchLabels: + app: mongodb + template: + metadata: + labels: + app: mongodb + spec: + securityContext: + runAsUser: 1001 + runAsGroup: 0 + fsGroup: 0 + runAsNonRoot: true + containers: + - name: mongodb + image: percona/percona-server-mongodb:8.0-community-k8s + imagePullPolicy: IfNotPresent + ports: + - containerPort: 27017 + name: mongodb + protocol: TCP + env: + - name: K8S_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MONGODB_DATA_DIR + value: /data/db + - name: MONGODB_LOG_DIR + value: /var/log/mongodb + - name: MONGODB_CONFIG_DIR + value: /etc/mongodb + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "500m" + volumeMounts: + - name: mongodb-data + mountPath: /data/db + - name: mongodb-logs + mountPath: /var/log/mongodb + - name: mongodb-config + mountPath: /etc/mongodb/mongod.conf.template + subPath: mongod.conf + readOnly: true + livenessProbe: + exec: + command: + - /healthcheck.sh + - liveness + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + exec: + command: + - /healthcheck.sh + - readiness + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + startupProbe: + exec: + command: + - /healthcheck.sh + - startup + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 30 + failureThreshold: 30 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 1001 + runAsGroup: 0 + capabilities: + drop: + - ALL + volumes: + - name: mongodb-data + emptyDir: {} + - name: mongodb-logs + emptyDir: {} + - name: mongodb-config + configMap: + name: mongodb-config + defaultMode: 0644 + terminationGracePeriodSeconds: 30 + restartPolicy: Always \ No newline at end of file diff --git a/percona-server-mongodb-8.0-community/mongodb.repo b/percona-server-mongodb-8.0-community/mongodb.repo index 8ea5273e..235f6f68 100644 --- a/percona-server-mongodb-8.0-community/mongodb.repo +++ b/percona-server-mongodb-8.0-community/mongodb.repo @@ -1,6 +1,6 @@ -[mongodb-org-8.2] +[mongodb-org-8.0] name=MongoDB Repository -baseurl=https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.2/$basearch/ +baseurl=https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.0/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://pgp.mongodb.com/server-8.0.asc diff --git a/percona-server-mongodb-8.2-community/.trivyignore b/percona-server-mongodb-8.2-community/.trivyignore new file mode 100644 index 00000000..25a7f002 --- /dev/null +++ b/percona-server-mongodb-8.2-community/.trivyignore @@ -0,0 +1,45 @@ +# Trivy Ignore File for MongoDB Community Edition 8.2 +# +# These vulnerabilities are in the MongoDB database tools (Go binaries) +# provided by MongoDB Inc. in the mongodb-database-tools package. +# +# MongoDB 8.2.3 includes mongodb-database-tools-100.14.0, but the tools +# are still compiled with Go 1.24.0, which has known vulnerabilities. +# These are upstream issues that require MongoDB to recompile the tools +# with a patched Go version (1.24.11+ or 1.25.5+). +# +# Affected binaries: +# - bsondump, mongodump, mongoexport, mongofiles +# - mongoimport, mongorestore, mongostat, mongotop +# +# MongoDB Version: 8.2.3 +# Database Tools Version: 100.14.0 +# Go Version (in tools): 1.24.0 +# +# Status: Waiting for MongoDB to recompile tools with Go 1.24.11+ or 1.25.5+ +# Last Updated: 2026-01-20 +# Review Date: Check monthly for MongoDB updates + +# CVE-2025-22874: crypto/x509 - ExtKeyUsageAny disables policy validation +# Severity: HIGH +# Fixed in: Go 1.24.4+ +# Component: stdlib in MongoDB database tools +CVE-2025-22874 + +# CVE-2025-47907: database/sql - Postgres Scan Race Condition +# Severity: HIGH +# Fixed in: Go 1.23.12, 1.24.6+ +# Component: stdlib in MongoDB database tools +CVE-2025-47907 + +# CVE-2025-58183: archive/tar - Unbounded allocation when parsing GNU sparse map +# Severity: HIGH +# Fixed in: Go 1.24.8, 1.25.2+ +# Component: stdlib in MongoDB database tools +CVE-2025-58183 + +# CVE-2025-61729: crypto/x509 - Denial of Service due to excessive resource consumption +# Severity: HIGH +# Fixed in: Go 1.24.11, 1.25.5+ +# Component: stdlib in MongoDB database tools +CVE-2025-61729 diff --git a/percona-server-mongodb-8.2-community/Dockerfile b/percona-server-mongodb-8.2-community/Dockerfile new file mode 100644 index 00000000..67a87d42 --- /dev/null +++ b/percona-server-mongodb-8.2-community/Dockerfile @@ -0,0 +1,78 @@ +FROM redhat/ubi9-minimal + +LABEL name="MongoDB Community Edition" \ + release="8.0" \ + vendor="MongoDB Inc." \ + summary="MongoDB Community Edition with Percona operator compatibility" \ + description="MongoDB Community Edition configured for use with Percona MongoDB operator" \ + maintainer="Percona Development " +LABEL org.opencontainers.image.authors="info@percona.com" + +ENV PSMDB_VERSION=8.2.3 +ENV OS_VER=el9 + +# Do not report during Docker image creation. +ARG PERCONA_TELEMETRY_DISABLE=1 + +COPY mongodb.repo /etc/yum.repos.d/mongodb.repo + +RUN set -ex; \ + microdnf -y update; \ + microdnf -y install \ + mongodb-org-${PSMDB_VERSION} \ + mongodb-org-database-${PSMDB_VERSION} \ + mongodb-org-server-${PSMDB_VERSION} \ + mongodb-mongosh \ + mongodb-org-mongos-${PSMDB_VERSION} \ + mongodb-org-tools-${PSMDB_VERSION} \ + numactl-libs \ + procps-ng \ + jq \ + tar \ + oniguruma \ + cyrus-sasl-gssapi \ + cyrus-sasl-plain; \ + microdnf clean all; \ + rm -rf /var/cache/yum /data/db && mkdir -p /data/db; \ + chown -R 1001:0 /data/db + +# the numeric UID is needed for OpenShift +RUN useradd -u 1001 -r -g 0 -m -s /sbin/nologin \ + -c "Default Application User" mongodb; \ + mkdir -p /var/log/mongo /etc/mongodb; \ + chmod g+rwx /var/log/mongo /etc/mongodb; \ + chown :0 /var/log/mongo /etc/mongodb + +COPY LICENSE /licenses/LICENSE.Dockerfile +RUN cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community || \ + echo "MongoDB Community License" > /licenses/LICENSE.MongoDB-Community + +ENV GOSU_VERSION=1.11 +RUN set -eux; \ + curl -Lf -o /usr/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64; \ + curl -Lf -o /usr/bin/gosu.asc https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ + rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ + \ + chmod +x /usr/bin/gosu; \ + curl -f -o /licenses/LICENSE.gosu https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE + +VOLUME ["/data/db"] + +RUN set -ex; \ + curl -fSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ + echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c - + +COPY ps-entry.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] + +EXPOSE 27017 + +USER 1001 + +CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-8.2-community/Dockerfile.k8s b/percona-server-mongodb-8.2-community/Dockerfile.k8s new file mode 100644 index 00000000..16924ab2 --- /dev/null +++ b/percona-server-mongodb-8.2-community/Dockerfile.k8s @@ -0,0 +1,198 @@ +# Multi-architecture MongoDB Community Edition for Kubernetes +# This Dockerfile is optimized for Kubernetes deployments with multi-arch support + +ARG TARGETARCH +ARG TARGETOS +ARG TARGETPLATFORM + +FROM --platform=${TARGETPLATFORM} redhat/ubi9-minimal + +# Kubernetes and OpenShift compatibility labels +LABEL name="MongoDB Community Edition for Kubernetes" \ + release="8.2" \ + version="8.2.3" \ + vendor="MongoDB Inc." \ + summary="MongoDB Community Edition optimized for Kubernetes with Percona operator compatibility" \ + description="Multi-architecture MongoDB Community Edition container optimized for Kubernetes deployments. Includes enhanced security, health checks, and operator integration." \ + maintainer="Percona Development " \ + io.k8s.description="MongoDB Community Edition for Kubernetes" \ + io.k8s.display-name="MongoDB Community 8.2" \ + io.openshift.expose-services="27017:mongodb" \ + io.openshift.tags="database,mongodb,nosql" + +LABEL org.opencontainers.image.title="MongoDB Community Edition for Kubernetes" \ + org.opencontainers.image.description="Multi-architecture MongoDB Community Edition optimized for Kubernetes" \ + org.opencontainers.image.version="8.2.3" \ + org.opencontainers.image.authors="info@percona.com" \ + org.opencontainers.image.vendor="Percona" \ + org.opencontainers.image.licenses="SSPL-1.0" \ + org.opencontainers.image.source="https://github.com/percona/percona-docker" \ + org.opencontainers.image.documentation="https://docs.percona.com/" + +# Environment variables for MongoDB and Kubernetes +ENV PSMDB_VERSION=8.2.3 \ + OS_VER=el9 \ + MONGODB_VERSION=8.2 \ + GOSU_VERSION=1.17 \ + PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +# Kubernetes-specific environment variables +ENV MONGODB_DATA_DIR=/data/db \ + MONGODB_LOG_DIR=/var/log/mongodb \ + MONGODB_CONFIG_DIR=/etc/mongodb \ + MONGODB_USER=mongodb \ + MONGODB_UID=1001 \ + MONGODB_GID=0 + +# Security and telemetry settings +ARG PERCONA_TELEMETRY_DISABLE=1 +ENV PERCONA_TELEMETRY_DISABLE=${PERCONA_TELEMETRY_DISABLE} + +# Copy repository configuration with architecture detection +COPY mongodb.repo /etc/yum.repos.d/mongodb.repo + +# Install MongoDB and dependencies with multi-arch support +RUN set -ex; \ + # Update system packages + microdnf -y update; \ + \ + # Install required system packages + microdnf -y install \ + shadow-utils \ + findutils \ + tar \ + gzip \ + procps-ng; \ + \ + # Install MongoDB packages + microdnf -y install \ + mongodb-org-${PSMDB_VERSION} \ + mongodb-org-database-${PSMDB_VERSION} \ + mongodb-org-server-${PSMDB_VERSION} \ + mongodb-mongosh \ + mongodb-org-mongos-${PSMDB_VERSION} \ + mongodb-org-tools-${PSMDB_VERSION} \ + numactl-libs \ + jq \ + oniguruma \ + cyrus-sasl-gssapi \ + cyrus-sasl-plain; \ + \ + # Clean up package cache + microdnf clean all; \ + rm -rf /var/cache/yum; \ + \ + # Create necessary directories with proper permissions + mkdir -p ${MONGODB_DATA_DIR} ${MONGODB_LOG_DIR} ${MONGODB_CONFIG_DIR} /tmp/mongodb; \ + \ + # Set up directory permissions for Kubernetes/OpenShift + chown -R ${MONGODB_UID}:${MONGODB_GID} ${MONGODB_DATA_DIR} ${MONGODB_LOG_DIR} ${MONGODB_CONFIG_DIR} /tmp/mongodb; \ + chmod -R g+rwx ${MONGODB_DATA_DIR} ${MONGODB_LOG_DIR} ${MONGODB_CONFIG_DIR} /tmp/mongodb; \ + chmod -R o-rwx ${MONGODB_DATA_DIR} ${MONGODB_LOG_DIR} ${MONGODB_CONFIG_DIR} + +# Create MongoDB user with Kubernetes/OpenShift compatibility +RUN set -ex; \ + # Create mongodb user with specific UID for Kubernetes + useradd -u ${MONGODB_UID} -r -g ${MONGODB_GID} -m -s /sbin/nologin \ + -c "MongoDB Application User" -d /home/mongodb ${MONGODB_USER}; \ + \ + # Ensure proper ownership and permissions + chown -R ${MONGODB_UID}:${MONGODB_GID} /home/mongodb; \ + chmod -R g+rwx /home/mongodb + +# Install gosu for privilege dropping with multi-arch support +RUN set -eux; \ + ARCH=$(uname -m); \ + case "$ARCH" in \ + x86_64) GOSU_ARCH="amd64" ;; \ + aarch64) GOSU_ARCH="arm64" ;; \ + *) echo "Unsupported architecture for gosu: $ARCH" && exit 1 ;; \ + esac; \ + \ + curl -fsSL -o /usr/bin/gosu "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${GOSU_ARCH}"; \ + curl -fsSL -o /usr/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${GOSU_ARCH}.asc"; \ + \ + export GNUPGHOME="$(mktemp -d)"; \ + gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ + gpg --batch --verify /usr/bin/gosu.asc /usr/bin/gosu; \ + rm -rf "$GNUPGHOME" /usr/bin/gosu.asc; \ + \ + chmod +x /usr/bin/gosu; \ + gosu --version; \ + gosu nobody true + +# Install js-yaml for configuration parsing +RUN set -ex; \ + curl -fsSL https://cdnjs.cloudflare.com/ajax/libs/js-yaml/4.1.0/js-yaml.min.js -o /js-yaml.js; \ + echo "45dc3dd03dc07a06705a2c2989b8c7f709013f04bd5386e3279d4e447f07ebd7 /js-yaml.js" | sha256sum -c -; \ + chmod 644 /js-yaml.js + +# Copy license files +COPY LICENSE /licenses/LICENSE.Dockerfile +RUN set -ex; \ + mkdir -p /licenses; \ + cp /usr/share/doc/mongodb-org-server/LICENSE-Community.txt /licenses/LICENSE.MongoDB-Community 2>/dev/null || \ + echo "MongoDB Community License (SSPL-1.0)" > /licenses/LICENSE.MongoDB-Community; \ + curl -fsSL -o /licenses/LICENSE.gosu "https://raw.githubusercontent.com/tianon/gosu/${GOSU_VERSION}/LICENSE"; \ + chmod 644 /licenses/* + +# Copy entrypoint and health check scripts +COPY ps-entry.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh + +# Set up scripts with proper permissions +RUN set -ex; \ + chmod +x /entrypoint.sh /healthcheck.sh; \ + chown ${MONGODB_UID}:${MONGODB_GID} /entrypoint.sh /healthcheck.sh + +# Create MongoDB configuration template +RUN set -ex; \ + cat > ${MONGODB_CONFIG_DIR}/mongod.conf.template << 'EOF' +# MongoDB configuration file template for Kubernetes +storage: + dbPath: /data/db + wiredTiger: + engineConfig: + cacheSizeGB: 0.25 + +systemLog: + destination: file + logAppend: true + path: /var/log/mongodb/mongod.log + logRotate: reopen + +net: + port: 27017 + bindIpAll: true + +processManagement: + timeZoneInfo: /usr/share/zoneinfo + +security: + authorization: disabled + +replication: + replSetName: rs0 + +operationProfiling: + slowOpThresholdMs: 100 +EOF + +# Set up health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ + CMD /healthcheck.sh + +# Kubernetes-specific volume declarations +VOLUME ["${MONGODB_DATA_DIR}", "${MONGODB_LOG_DIR}"] + +# Expose MongoDB port +EXPOSE 27017 + +# Use entrypoint for MongoDB initialization +ENTRYPOINT ["/entrypoint.sh"] + +# Switch to non-root user +USER ${MONGODB_UID} + +# Default command +CMD ["mongod"] \ No newline at end of file diff --git a/percona-server-mongodb-8.2-community/LICENSE b/percona-server-mongodb-8.2-community/LICENSE new file mode 100644 index 00000000..0ae7afb4 --- /dev/null +++ b/percona-server-mongodb-8.2-community/LICENSE @@ -0,0 +1,7 @@ +MongoDB Community Edition License + +This software is licensed under the Server Side Public License (SSPL) v1. +For more information, see: https://www.mongodb.com/licensing/server-side-public-license + +This Docker image contains MongoDB Community Edition binaries and is configured +for use with the Percona MongoDB Operator for Kubernetes. \ No newline at end of file diff --git a/percona-server-mongodb-8.2-community/healthcheck.sh b/percona-server-mongodb-8.2-community/healthcheck.sh new file mode 100644 index 00000000..63edfa77 --- /dev/null +++ b/percona-server-mongodb-8.2-community/healthcheck.sh @@ -0,0 +1,236 @@ +#!/bin/bash +# MongoDB Health Check Script for Kubernetes + +set -euo pipefail + +# Configuration +MONGODB_HOST="${MONGODB_HOST:-localhost}" +MONGODB_PORT="${MONGODB_PORT:-27017}" +MONGODB_DATABASE="${MONGODB_DATABASE:-admin}" +TIMEOUT="${HEALTH_CHECK_TIMEOUT:-10}" +MAX_RETRIES="${HEALTH_CHECK_RETRIES:-3}" + +# Logging function +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] HEALTHCHECK: $*" >&2 +} + +# Function to check if MongoDB is accepting connections +check_connection() { + local retry=0 + while [ $retry -lt $MAX_RETRIES ]; do + if timeout $TIMEOUT mongosh --host "$MONGODB_HOST" --port "$MONGODB_PORT" --quiet --eval "db.adminCommand('ping')" >/dev/null 2>&1; then + return 0 + fi + retry=$((retry + 1)) + log "Connection attempt $retry failed, retrying..." + sleep 1 + done + return 1 +} + +# Function to check MongoDB server status +check_server_status() { + local status_output + status_output=$(timeout $TIMEOUT mongosh --host "$MONGODB_HOST" --port "$MONGODB_PORT" --quiet --eval " + try { + var status = db.adminCommand('serverStatus'); + if (status.ok === 1) { + print('OK'); + } else { + print('ERROR: Server status not OK'); + } + } catch (e) { + print('ERROR: ' + e.message); + } + " 2>/dev/null) + + if [[ "$status_output" == "OK" ]]; then + return 0 + else + log "Server status check failed: $status_output" + return 1 + fi +} + +# Function to check if MongoDB is ready for read/write operations +check_readiness() { + local readiness_output + readiness_output=$(timeout $TIMEOUT mongosh --host "$MONGODB_HOST" --port "$MONGODB_PORT" --quiet --eval " + try { + // Check if we can perform basic operations + db.healthcheck.insertOne({timestamp: new Date(), check: 'readiness'}); + db.healthcheck.findOne({check: 'readiness'}); + db.healthcheck.deleteMany({check: 'readiness'}); + print('READY'); + } catch (e) { + print('NOT_READY: ' + e.message); + } + " 2>/dev/null) + + if [[ "$readiness_output" == "READY" ]]; then + return 0 + else + log "Readiness check failed: $readiness_output" + return 1 + fi +} + +# Function to check replica set status (if applicable) +check_replica_set() { + local rs_output + rs_output=$(timeout $TIMEOUT mongosh --host "$MONGODB_HOST" --port "$MONGODB_PORT" --quiet --eval " + try { + var status = rs.status(); + if (status.ok === 1) { + var myState = status.members.find(m => m.self === true); + if (myState && (myState.state === 1 || myState.state === 2)) { + print('RS_OK'); + } else { + print('RS_NOT_READY: State ' + (myState ? myState.state : 'unknown')); + } + } else { + print('RS_ERROR: ' + status.errmsg); + } + } catch (e) { + // Not a replica set or not initialized yet + print('RS_NOT_CONFIGURED'); + } + " 2>/dev/null) + + case "$rs_output" in + "RS_OK") + log "Replica set status: OK" + return 0 + ;; + "RS_NOT_CONFIGURED") + log "Replica set not configured (standalone mode)" + return 0 + ;; + *) + log "Replica set check failed: $rs_output" + return 1 + ;; + esac +} + +# Function to check disk space +check_disk_space() { + local data_dir="${MONGODB_DATA_DIR:-/data/db}" + local log_dir="${MONGODB_LOG_DIR:-/var/log/mongodb}" + local min_free_percent="${MIN_FREE_DISK_PERCENT:-10}" + + for dir in "$data_dir" "$log_dir"; do + if [[ -d "$dir" ]]; then + local usage + usage=$(df "$dir" | awk 'NR==2 {print $5}' | sed 's/%//') + local free_percent=$((100 - usage)) + + if [[ $free_percent -lt $min_free_percent ]]; then + log "Disk space warning: $dir has only $free_percent% free (minimum: $min_free_percent%)" + return 1 + fi + fi + done + return 0 +} + +# Function to check process health +check_process_health() { + # Check if mongod process is running + if ! pgrep -f mongod >/dev/null 2>&1; then + log "MongoDB process not found" + return 1 + fi + + # Check if process is responsive (not in uninterruptible sleep) + local mongod_pid + mongod_pid=$(pgrep -f mongod | head -1) + if [[ -n "$mongod_pid" ]]; then + local process_state + process_state=$(ps -o state= -p "$mongod_pid" 2>/dev/null | tr -d ' ') + if [[ "$process_state" == "D" ]]; then + log "MongoDB process is in uninterruptible sleep state" + return 1 + fi + fi + + return 0 +} + +# Main health check function +main() { + local exit_code=0 + local check_type="${1:-full}" + + log "Starting health check (type: $check_type)" + + # Always check process health first + if ! check_process_health; then + log "Process health check failed" + exit_code=1 + fi + + # Check MongoDB connection + if ! check_connection; then + log "Connection check failed" + exit_code=1 + fi + + # For full health checks, perform additional tests + if [[ "$check_type" == "full" ]]; then + # Check server status + if ! check_server_status; then + log "Server status check failed" + exit_code=1 + fi + + # Check readiness for operations + if ! check_readiness; then + log "Readiness check failed" + exit_code=1 + fi + + # Check replica set status if applicable + if ! check_replica_set; then + log "Replica set check failed" + exit_code=1 + fi + + # Check disk space + if ! check_disk_space; then + log "Disk space check failed" + exit_code=1 + fi + fi + + if [[ $exit_code -eq 0 ]]; then + log "Health check passed" + else + log "Health check failed" + fi + + exit $exit_code +} + +# Handle different invocation modes +case "${1:-full}" in + "liveness"|"live") + # Liveness probe - basic connection check + main "basic" + ;; + "readiness"|"ready") + # Readiness probe - full functionality check + main "full" + ;; + "startup") + # Startup probe - basic connection with retries + MAX_RETRIES=10 + TIMEOUT=30 + main "basic" + ;; + *) + # Default full health check + main "full" + ;; +esac diff --git a/percona-server-mongodb-8.2-community/k8s-examples/mongodb-deployment.yaml b/percona-server-mongodb-8.2-community/k8s-examples/mongodb-deployment.yaml new file mode 100644 index 00000000..c4ab31bb --- /dev/null +++ b/percona-server-mongodb-8.2-community/k8s-examples/mongodb-deployment.yaml @@ -0,0 +1,231 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: mongodb + labels: + name: mongodb +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mongodb-config + namespace: mongodb +data: + mongod.conf: | + # MongoDB configuration for Kubernetes + storage: + dbPath: /data/db + journal: + enabled: true + wiredTiger: + engineConfig: + cacheSizeGB: 1.0 + + systemLog: + destination: file + logAppend: true + path: /var/log/mongodb/mongod.log + logRotate: reopen + verbosity: 1 + + net: + port: 27017 + bindIpAll: true + maxIncomingConnections: 1000 + + processManagement: + timeZoneInfo: /usr/share/zoneinfo + + security: + authorization: enabled + + replication: + replSetName: rs0 + + operationProfiling: + slowOpThresholdMs: 100 + mode: slowOp +--- +apiVersion: v1 +kind: Secret +metadata: + name: mongodb-secret + namespace: mongodb +type: Opaque +data: + # echo -n 'admin' | base64 + username: YWRtaW4= + # echo -n 'SecurePassword123!' | base64 + password: U2VjdXJlUGFzc3dvcmQxMjMh +--- +apiVersion: v1 +kind: Service +metadata: + name: mongodb-service + namespace: mongodb + labels: + app: mongodb +spec: + type: ClusterIP + ports: + - port: 27017 + targetPort: 27017 + protocol: TCP + name: mongodb + selector: + app: mongodb +--- +apiVersion: v1 +kind: Service +metadata: + name: mongodb-headless + namespace: mongodb + labels: + app: mongodb +spec: + type: ClusterIP + clusterIP: None + ports: + - port: 27017 + targetPort: 27017 + protocol: TCP + name: mongodb + selector: + app: mongodb +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mongodb + namespace: mongodb + labels: + app: mongodb +spec: + serviceName: mongodb-headless + replicas: 3 + selector: + matchLabels: + app: mongodb + template: + metadata: + labels: + app: mongodb + spec: + securityContext: + runAsUser: 1001 + runAsGroup: 0 + fsGroup: 0 + runAsNonRoot: true + containers: + - name: mongodb + image: percona/percona-server-mongodb:8.0-community-k8s + imagePullPolicy: IfNotPresent + ports: + - containerPort: 27017 + name: mongodb + protocol: TCP + env: + - name: MONGO_INITDB_ROOT_USERNAME_FILE + value: /etc/mongodb-secret/username + - name: MONGO_INITDB_ROOT_PASSWORD_FILE + value: /etc/mongodb-secret/password + - name: MONGO_INITDB_DATABASE + value: admin + - name: REPLICA_SET_NAME + value: rs0 + - name: K8S_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: K8S_SERVICE_NAME + value: mongodb-headless + - name: MONGODB_DATA_DIR + value: /data/db + - name: MONGODB_LOG_DIR + value: /var/log/mongodb + - name: MONGODB_CONFIG_DIR + value: /etc/mongodb + resources: + requests: + memory: "512Mi" + cpu: "250m" + limits: + memory: "2Gi" + cpu: "1000m" + volumeMounts: + - name: mongodb-data + mountPath: /data/db + - name: mongodb-logs + mountPath: /var/log/mongodb + - name: mongodb-config + mountPath: /etc/mongodb/mongod.conf.template + subPath: mongod.conf + readOnly: true + - name: mongodb-secret + mountPath: /etc/mongodb-secret + readOnly: true + livenessProbe: + exec: + command: + - /healthcheck.sh + - liveness + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 10 + failureThreshold: 3 + successThreshold: 1 + readinessProbe: + exec: + command: + - /healthcheck.sh + - readiness + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + successThreshold: 1 + startupProbe: + exec: + command: + - /healthcheck.sh + - startup + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 30 + failureThreshold: 30 + successThreshold: 1 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 1001 + runAsGroup: 0 + capabilities: + drop: + - ALL + volumes: + - name: mongodb-config + configMap: + name: mongodb-config + defaultMode: 0644 + - name: mongodb-secret + secret: + secretName: mongodb-secret + defaultMode: 0400 + - name: mongodb-logs + emptyDir: {} + terminationGracePeriodSeconds: 30 + restartPolicy: Always + volumeClaimTemplates: + - metadata: + name: mongodb-data + spec: + accessModes: ["ReadWriteOnce"] + storageClassName: "standard" + resources: + requests: + storage: 10Gi \ No newline at end of file diff --git a/percona-server-mongodb-8.2-community/k8s-examples/mongodb-simple.yaml b/percona-server-mongodb-8.2-community/k8s-examples/mongodb-simple.yaml new file mode 100644 index 00000000..4ab29401 --- /dev/null +++ b/percona-server-mongodb-8.2-community/k8s-examples/mongodb-simple.yaml @@ -0,0 +1,158 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: mongodb-simple +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mongodb-config + namespace: mongodb-simple +data: + mongod.conf: | + # Simple MongoDB configuration for Kubernetes + storage: + dbPath: /data/db + journal: + enabled: true + + systemLog: + destination: file + logAppend: true + path: /var/log/mongodb/mongod.log + + net: + port: 27017 + bindIpAll: true + + processManagement: + timeZoneInfo: /usr/share/zoneinfo + + security: + authorization: disabled +--- +apiVersion: v1 +kind: Service +metadata: + name: mongodb + namespace: mongodb-simple + labels: + app: mongodb +spec: + type: ClusterIP + ports: + - port: 27017 + targetPort: 27017 + protocol: TCP + name: mongodb + selector: + app: mongodb +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mongodb + namespace: mongodb-simple + labels: + app: mongodb +spec: + replicas: 1 + selector: + matchLabels: + app: mongodb + template: + metadata: + labels: + app: mongodb + spec: + securityContext: + runAsUser: 1001 + runAsGroup: 0 + fsGroup: 0 + runAsNonRoot: true + containers: + - name: mongodb + image: percona/percona-server-mongodb:8.0-community-k8s + imagePullPolicy: IfNotPresent + ports: + - containerPort: 27017 + name: mongodb + protocol: TCP + env: + - name: K8S_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: MONGODB_DATA_DIR + value: /data/db + - name: MONGODB_LOG_DIR + value: /var/log/mongodb + - name: MONGODB_CONFIG_DIR + value: /etc/mongodb + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "500m" + volumeMounts: + - name: mongodb-data + mountPath: /data/db + - name: mongodb-logs + mountPath: /var/log/mongodb + - name: mongodb-config + mountPath: /etc/mongodb/mongod.conf.template + subPath: mongod.conf + readOnly: true + livenessProbe: + exec: + command: + - /healthcheck.sh + - liveness + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 10 + failureThreshold: 3 + readinessProbe: + exec: + command: + - /healthcheck.sh + - readiness + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + startupProbe: + exec: + command: + - /healthcheck.sh + - startup + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 30 + failureThreshold: 30 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 1001 + runAsGroup: 0 + capabilities: + drop: + - ALL + volumes: + - name: mongodb-data + emptyDir: {} + - name: mongodb-logs + emptyDir: {} + - name: mongodb-config + configMap: + name: mongodb-config + defaultMode: 0644 + terminationGracePeriodSeconds: 30 + restartPolicy: Always \ No newline at end of file diff --git a/percona-server-mongodb-8.2-community/mongodb.repo b/percona-server-mongodb-8.2-community/mongodb.repo new file mode 100644 index 00000000..8ea5273e --- /dev/null +++ b/percona-server-mongodb-8.2-community/mongodb.repo @@ -0,0 +1,10 @@ +[mongodb-org-8.2] +name=MongoDB Repository +baseurl=https://repo.mongodb.org/yum/redhat/9/mongodb-org/8.2/$basearch/ +gpgcheck=1 +enabled=1 +gpgkey=https://pgp.mongodb.com/server-8.0.asc +sslverify=1 +sslcacert=/etc/pki/tls/certs/ca-bundle.crt +metadata_expire=300 +repo_gpgcheck=1 diff --git a/percona-server-mongodb-8.2-community/ps-entry.sh b/percona-server-mongodb-8.2-community/ps-entry.sh new file mode 100644 index 00000000..735468ae --- /dev/null +++ b/percona-server-mongodb-8.2-community/ps-entry.sh @@ -0,0 +1,332 @@ +#!/bin/bash +# Enhanced MongoDB Entrypoint Script for Kubernetes +# Optimized for Kubernetes deployments with improved signal handling, configuration management, and operator integration + +set -Eeuo pipefail + +# Configuration variables +MONGODB_DATA_DIR="${MONGODB_DATA_DIR:-/data/db}" +MONGODB_LOG_DIR="${MONGODB_LOG_DIR:-/var/log/mongodb}" +MONGODB_CONFIG_DIR="${MONGODB_CONFIG_DIR:-/etc/mongodb}" +MONGODB_USER="${MONGODB_USER:-mongodb}" +MONGODB_UID="${MONGODB_UID:-1001}" +MONGODB_GID="${MONGODB_GID:-0}" + +# Kubernetes-specific variables +K8S_NAMESPACE="${K8S_NAMESPACE:-}" +K8S_POD_NAME="${K8S_POD_NAME:-}" +K8S_SERVICE_NAME="${K8S_SERVICE_NAME:-}" +REPLICA_SET_NAME="${REPLICA_SET_NAME:-rs0}" + +# Logging function +log() { + echo "[$(date +'%Y-%m-%d %H:%M:%S')] ENTRYPOINT: $*" >&2 +} + +# Error handling +error_exit() { + log "ERROR: $1" + exit 1 +} + +# Signal handling for graceful shutdown +shutdown_handler() { + log "Received shutdown signal, initiating graceful shutdown..." + + # If MongoDB is running, try to shut it down gracefully + if pgrep -f mongod >/dev/null 2>&1; then + log "Shutting down MongoDB gracefully..." + + # Try to use MongoDB's shutdown command first + if mongosh --quiet --eval "db.adminCommand('shutdown')" >/dev/null 2>&1; then + log "MongoDB shutdown command sent successfully" + else + log "MongoDB shutdown command failed, sending SIGTERM to process" + pkill -TERM mongod || true + fi + + # Wait for process to exit gracefully + local timeout=30 + while pgrep -f mongod >/dev/null 2>&1 && [ $timeout -gt 0 ]; do + sleep 1 + timeout=$((timeout - 1)) + done + + if pgrep -f mongod >/dev/null 2>&1; then + log "MongoDB did not shut down gracefully, sending SIGKILL" + pkill -KILL mongod || true + else + log "MongoDB shut down gracefully" + fi + fi + + exit 0 +} + +# Set up signal handlers +trap shutdown_handler SIGTERM SIGINT SIGQUIT + +# Function to setup directories and permissions +setup_directories() { + log "Setting up directories and permissions..." + + # Create necessary directories + for dir in "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" "$MONGODB_CONFIG_DIR" "/tmp/mongodb"; do + if [[ ! -d "$dir" ]]; then + mkdir -p "$dir" + log "Created directory: $dir" + fi + done + + # Set ownership and permissions for Kubernetes/OpenShift compatibility + chown -R "$MONGODB_UID:$MONGODB_GID" "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" "$MONGODB_CONFIG_DIR" "/tmp/mongodb" 2>/dev/null || true + chmod -R g+rwx "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" "$MONGODB_CONFIG_DIR" "/tmp/mongodb" 2>/dev/null || true + chmod -R o-rwx "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" "$MONGODB_CONFIG_DIR" 2>/dev/null || true +} + +# Function to handle file-based environment variables (Kubernetes secrets) +file_env() { + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + + if [[ -n "${!var:-}" ]] && [[ -n "${!fileVar:-}" ]]; then + error_exit "Both $var and $fileVar are set (but are exclusive)" + fi + + local val="$def" + if [[ -n "${!var:-}" ]]; then + val="${!var}" + elif [[ -n "${!fileVar:-}" ]]; then + if [[ -f "${!fileVar}" ]]; then + val="$(< "${!fileVar}")" + else + error_exit "File ${!fileVar} does not exist" + fi + fi + + export "$var"="$val" + unset "$fileVar" 2>/dev/null || true +} + +# Function to generate MongoDB configuration +generate_config() { + local config_file="$MONGODB_CONFIG_DIR/mongod.conf" + + log "Generating MongoDB configuration..." + + # Start with template if it exists + if [[ -f "$MONGODB_CONFIG_DIR/mongod.conf.template" ]]; then + cp "$MONGODB_CONFIG_DIR/mongod.conf.template" "$config_file" + else + # Create basic configuration + cat > "$config_file" << EOF +# MongoDB configuration for Kubernetes +storage: + dbPath: $MONGODB_DATA_DIR + journal: + enabled: true + +systemLog: + destination: file + logAppend: true + path: $MONGODB_LOG_DIR/mongod.log + logRotate: reopen + +net: + port: 27017 + bindIpAll: true + +processManagement: + timeZoneInfo: /usr/share/zoneinfo + +security: + authorization: disabled +EOF + fi + + # Add replica set configuration if specified + if [[ -n "$REPLICA_SET_NAME" ]]; then + if ! grep -q "replication:" "$config_file"; then + cat >> "$config_file" << EOF + +replication: + replSetName: $REPLICA_SET_NAME +EOF + fi + fi + + # Set proper permissions + chown "$MONGODB_UID:$MONGODB_GID" "$config_file" + chmod 640 "$config_file" + + log "MongoDB configuration generated at $config_file" +} + +# Function to wait for network readiness +wait_for_network() { + log "Waiting for network readiness..." + + local timeout=30 + while [ $timeout -gt 0 ]; do + if ss -tuln | grep -q ":27017 "; then + log "Port 27017 is already in use, waiting..." + sleep 1 + timeout=$((timeout - 1)) + else + break + fi + done + + if [ $timeout -eq 0 ]; then + log "Warning: Port 27017 may still be in use" + fi +} + +# Function to initialize MongoDB if needed +initialize_mongodb() { + log "Checking if MongoDB initialization is needed..." + + # Check if this is a fresh installation + if [[ ! -f "$MONGODB_DATA_DIR/WiredTiger" ]] && [[ ! -f "$MONGODB_DATA_DIR/mongod.lock" ]]; then + log "Fresh MongoDB installation detected" + + # Handle initialization scripts + file_env 'MONGO_INITDB_ROOT_USERNAME' + file_env 'MONGO_INITDB_ROOT_PASSWORD' + file_env 'MONGO_INITDB_DATABASE' + + if [[ -n "${MONGO_INITDB_ROOT_USERNAME:-}" ]] && [[ -n "${MONGO_INITDB_ROOT_PASSWORD:-}" ]]; then + log "Root user credentials provided, will initialize with authentication" + export MONGO_INITDB_ROOT_USERNAME + export MONGO_INITDB_ROOT_PASSWORD + export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-admin}" + fi + else + log "Existing MongoDB data found, skipping initialization" + fi +} + +# Function to setup MongoDB arguments with Kubernetes optimizations +setup_mongodb_args() { + local -a mongod_args=("$@") + + # If no arguments provided, use default + if [[ ${#mongod_args[@]} -eq 0 ]]; then + mongod_args=("mongod") + fi + + # If first argument starts with -, prepend mongod + if [[ "${mongod_args[0]:0:1}" = '-' ]]; then + mongod_args=("mongod" "${mongod_args[@]}") + fi + + # Add Kubernetes-specific optimizations + local -a k8s_args=() + + # Use configuration file if it exists + if [[ -f "$MONGODB_CONFIG_DIR/mongod.conf" ]]; then + k8s_args+=("--config" "$MONGODB_CONFIG_DIR/mongod.conf") + fi + + # Kubernetes-specific settings + k8s_args+=( + "--bind_ip_all" + "--logpath" "$MONGODB_LOG_DIR/mongod.log" + "--logappend" + ) + + # Add NUMA optimization if available + if command -v numactl >/dev/null 2>&1 && numactl --hardware >/dev/null 2>&1; then + mongod_args=("numactl" "--interleave=all" "${mongod_args[@]}") + fi + + # Combine arguments + mongod_args+=("${k8s_args[@]}") + + echo "${mongod_args[@]}" +} + +# Function to start MongoDB with proper user switching +start_mongodb() { + local -a mongod_cmd=($@) + + log "Starting MongoDB with command: ${mongod_cmd[*]}" + + # Ensure we're running as the correct user + if [[ "$(id -u)" = '0' ]]; then + # Running as root, switch to mongodb user + log "Running as root, switching to user $MONGODB_USER (UID: $MONGODB_UID)" + + # Ensure ownership of critical files + chown "$MONGODB_UID:$MONGODB_GID" "$MONGODB_DATA_DIR" "$MONGODB_LOG_DIR" 2>/dev/null || true + + # Use gosu to switch user and exec + exec gosu "$MONGODB_UID:$MONGODB_GID" "${mongod_cmd[@]}" + else + # Already running as non-root user + log "Running as user $(id -un) (UID: $(id -u))" + exec "${mongod_cmd[@]}" + fi +} + +# Function to check if command is MongoDB-related +is_mongodb_command() { + local cmd="$1" + + # List of MongoDB-related commands + case "$cmd" in + mongod|mongos|mongo|mongosh) + return 0 + ;; + *) + return 1 + ;; + esac +} + +# Main execution function +main() { + # Check if we should run MongoDB initialization or just exec the command + local first_arg="${1:-mongod}" + + # If the first argument is not a MongoDB command, just exec it directly + # This allows for command overrides like: docker run image echo "hello" + if ! is_mongodb_command "$first_arg"; then + log "Non-MongoDB command detected: $first_arg" + log "Executing command directly without MongoDB initialization" + + # If running as root, switch to mongodb user for consistency + if [[ "$(id -u)" = '0' ]]; then + exec gosu "$MONGODB_UID:$MONGODB_GID" "$@" + else + exec "$@" + fi + fi + + # MongoDB command detected, proceed with full initialization + log "Starting MongoDB entrypoint for Kubernetes..." + log "Pod: ${K8S_POD_NAME:-unknown}, Namespace: ${K8S_NAMESPACE:-unknown}" + + # Setup directories and permissions + setup_directories + + # Wait for network readiness + wait_for_network + + # Generate configuration + generate_config + + # Initialize MongoDB if needed + initialize_mongodb + + # Setup MongoDB arguments + local -a final_args + IFS=' ' read -ra final_args <<< "$(setup_mongodb_args "$@")" + + # Start MongoDB + start_mongodb "${final_args[@]}" +} + +# Execute main function with all arguments +main "$@" \ No newline at end of file