-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update mariadb #6965
Merged
Merged
Update mariadb #6965
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Changes: - MariaDB/mariadb-docker@3b2e52a: Merge pull request MariaDB/mariadb-docker#271 from infosiftr/rsync-with-mysql
Diff:diff --git a/mariadb_10.1/docker-entrypoint.sh b/mariadb_10.1/docker-entrypoint.sh
index 7ee5efd..77c5d4c 100755
--- a/mariadb_10.1/docker-entrypoint.sh
+++ b/mariadb_10.1/docker-entrypoint.sh
@@ -2,21 +2,21 @@
set -eo pipefail
shopt -s nullglob
-# if command starts with an option, prepend mysqld
-if [ "${1:0:1}" = '-' ]; then
- set -- mysqld "$@"
-fi
-
-# skip setup if they want an option that stops mysqld
-wantHelp=
-for arg; do
- case "$arg" in
- -'?'|--help|--print-defaults|-V|--version)
- wantHelp=1
- break
- ;;
- esac
-done
+# logging functions
+mysql_log() {
+ local type="$1"; shift
+ printf '%s [%s] [Entrypoint]: %s\n' "$(date --rfc-3339=seconds)" "$type" "$*"
+}
+mysql_note() {
+ mysql_log Note "$@"
+}
+mysql_warn() {
+ mysql_log Warn "$@" >&2
+}
+mysql_error() {
+ mysql_log ERROR "$@" >&2
+ exit 1
+}
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
@@ -27,8 +27,7 @@ file_env() {
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
+ mysql_error "Both $var and $fileVar are set (but are exclusive)"
fi
local val="$def"
if [ "${!var:-}" ]; then
@@ -40,56 +39,106 @@ file_env() {
unset "$fileVar"
}
-_check_config() {
- toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" )
- if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
- cat >&2 <<-EOM
+# check to see if this file is being run or sourced from another script
+_is_sourced() {
+ # https://unix.stackexchange.com/a/215279
+ [ "${#FUNCNAME[@]}" -ge 2 ] \
+ && [ "${FUNCNAME[0]}" = '_is_sourced' ] \
+ && [ "${FUNCNAME[1]}" = 'source' ]
+}
- ERROR: mysqld failed while attempting to check config
- command was: "${toRun[*]}"
+# usage: docker_process_init_files [file [file [...]]]
+# ie: docker_process_init_files /always-initdb.d/*
+# process initializer files, based on file extensions
+docker_process_init_files() {
+ # mysql here for backwards compatibility "${mysql[@]}"
+ mysql=( docker_process_sql )
- $errors
- EOM
- exit 1
+ echo
+ local f
+ for f; do
+ case "$f" in
+ *.sh) mysql_note "$0: running $f"; . "$f" ;;
+ *.sql) mysql_note "$0: running $f"; docker_process_sql < "$f"; echo ;;
+ *.sql.gz) mysql_note "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;;
+ *) mysql_warn "$0: ignoring $f" ;;
+ esac
+ echo
+ done
+}
+
+mysql_check_config() {
+ local toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" ) errors
+ if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
+ mysql_error $'mysqld failed while attempting to check config\n\tcommand was: '"${toRun[*]}"$'\n\t'"$errors"
fi
}
# Fetch value from server config
# We use mysqld --verbose --help instead of my_print_defaults because the
# latter only show values present in config files, and not server defaults
-_get_config() {
+mysql_get_config() {
local conf="$1"; shift
"$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null \
- | awk '$1 == "'"$conf"'" && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
+ | awk -v conf="$conf" '$1 == conf && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
# match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)"
}
-# allow the container to be started with `--user`
-if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then
- _check_config "$@"
- DATADIR="$(_get_config 'datadir' "$@")"
- mkdir -p "$DATADIR"
- find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
- exec gosu mysql "$BASH_SOURCE" "$@"
-fi
+# Do a temporary startup of the MySQL server, for init purposes
+docker_temp_server_start() {
+ "$@" --skip-networking --socket="${SOCKET}" &
+ mysql_note "Waiting for server startup"
+ local i
+ for i in {30..0}; do
+ # only use the root password if the database has already been initializaed
+ # so that it won't try to fill in a password file when it hasn't been set yet
+ extraArgs=()
+ if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
+ extraArgs+=( '--dont-use-mysql-root-password' )
+ fi
+ if docker_process_sql "${extraArgs[@]}" --database=mysql <<<'SELECT 1' &> /dev/null; then
+ break
+ fi
+ sleep 1
+ done
+ if [ "$i" = 0 ]; then
+ mysql_error "Unable to start server."
+ fi
+}
-if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
- # still need to check config, container may have started with --user
- _check_config "$@"
- # Get config
- DATADIR="$(_get_config 'datadir' "$@")"
+# Stop the server. When using a local socket file mysqladmin will block until
+# the shutdown is complete.
+docker_temp_server_stop() {
+ if ! mysqladmin --defaults-extra-file=<( _mysql_passfile ) shutdown -uroot --socket="${SOCKET}"; then
+ mysql_error "Unable to shut down server."
+ fi
+}
- if [ ! -d "$DATADIR/mysql" ]; then
- file_env 'MYSQL_ROOT_PASSWORD'
+# Verify that the minimally required password settings are set for new databases.
+docker_verify_minimum_env() {
if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
- echo >&2 'error: database is uninitialized and password option is not specified '
- echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
- exit 1
+ mysql_error $'Database is uninitialized and password option is not specified\n\tYou need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
fi
+}
+
+# creates folders for the database
+# also ensures permission for user mysql of run as root
+docker_create_db_directories() {
+ local user; user="$(id -u)"
+ # TODO other directories that are used by default? like /var/lib/mysql-files
+ # see https://github.com/docker-library/mysql/issues/562
mkdir -p "$DATADIR"
- echo 'Initializing database'
+ if [ "$user" = "0" ]; then
+ # this will cause less disk access than `chown -R`
+ find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
+ fi
+}
+
+# initializes the database directory
+docker_init_database_dir() {
+ mysql_note "Initializing database files"
installArgs=( --datadir="$DATADIR" --rpm )
if { mysql_install_db --help || :; } | grep -q -- '--auth-root-authentication-method'; then
# beginning in 10.4.3, install_db uses "socket" which only allows system user root to connect, switch back to "normal" to allow mysql root without a password
@@ -99,40 +148,67 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
fi
# "Other options are passed to mysqld." (so we pass all "mysqld" arguments directly here)
mysql_install_db "${installArgs[@]}" "${@:2}"
- echo 'Database initialized'
+ mysql_note "Database files initialized"
+}
- SOCKET="$(_get_config 'socket' "$@")"
- "$@" --skip-networking --socket="${SOCKET}" &
- pid="$!"
+# Loads various settings that are used elsewhere in the script
+# This should be called after mysql_check_config, but before any other functions
+docker_setup_env() {
+ # Get config
+ declare -g DATADIR SOCKET
+ DATADIR="$(mysql_get_config 'datadir' "$@")"
+ SOCKET="$(mysql_get_config 'socket' "$@")"
- mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )
+ # Initialize values that might be stored in a file
+ file_env 'MYSQL_ROOT_HOST' '%'
+ file_env 'MYSQL_DATABASE'
+ file_env 'MYSQL_USER'
+ file_env 'MYSQL_PASSWORD'
+ file_env 'MYSQL_ROOT_PASSWORD'
- for i in {30..0}; do
- if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then
- break
+ declare -g DATABASE_ALREADY_EXISTS
+ if [ -d "$DATADIR/mysql" ]; then
+ DATABASE_ALREADY_EXISTS='true'
fi
- echo 'MySQL init process in progress...'
- sleep 1
- done
- if [ "$i" = 0 ]; then
- echo >&2 'MySQL init process failed.'
- exit 1
+}
+
+# Execute sql script, passed via stdin
+# usage: docker_process_sql [--dont-use-mysql-root-password] [mysql-cli-args]
+# ie: docker_process_sql --database=mydb <<<'INSERT ...'
+# ie: docker_process_sql --dont-use-mysql-root-password --database=mydb <my-file.sql
+docker_process_sql() {
+ passfileArgs=()
+ if [ '--dont-use-mysql-root-password' = "$1" ]; then
+ passfileArgs+=( "$1" )
+ shift
fi
+ # args sent in can override this db, since they will be later in the command
+ if [ -n "$MYSQL_DATABASE" ]; then
+ set -- --database="$MYSQL_DATABASE" "$@"
+ fi
+
+ mysql --defaults-file=<( _mysql_passfile "${passfileArgs[@]}") --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" "$@"
+}
+# Initializes database with timezone info and root password, plus optional extra db/user
+docker_setup_db() {
+ # Load timezone info into database
if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then
# sed is for https://bugs.mysql.com/bug.php?id=20545
- mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql
+ mysql_tzinfo_to_sql /usr/share/zoneinfo \
+ | sed 's/Local time zone must be set--see zic manual page/FCTY/' \
+ | docker_process_sql --dont-use-mysql-root-password --database=mysql
+ # tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is not set yet
fi
-
- if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
+ # Generate random root password
+ if [ -n "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)"
- echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
+ mysql_note "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
fi
-
- rootCreate=
+ # Sets root password and creates root users for non-localhost hosts
+ local rootCreate=
# default root to listen for connections from anywhere
- file_env 'MYSQL_ROOT_HOST' '%'
- if [ ! -z "$MYSQL_ROOT_HOST" -a "$MYSQL_ROOT_HOST" != 'localhost' ]; then
+ if [ -n "$MYSQL_ROOT_HOST" ] && [ "$MYSQL_ROOT_HOST" != 'localhost' ]; then
# no, we don't care if read finds a terminating character in this heredoc
# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151
read -r -d '' rootCreate <<-EOSQL || true
@@ -141,59 +217,115 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
EOSQL
fi
- "${mysql[@]}" <<-EOSQL
+ # tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is just now being set
+ docker_process_sql --dont-use-mysql-root-password --database=mysql <<-EOSQL
-- What's done in this file shouldn't be replicated
-- or products like mysql-fabric won't work
SET @@SESSION.SQL_LOG_BIN=0;
DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ;
SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ;
+ -- 10.1: https://github.com/MariaDB/server/blob/d925aec1c10cebf6c34825a7de50afe4e630aff4/scripts/mysql_secure_installation.sh#L347-L365
+ -- 10.5: https://github.com/MariaDB/server/blob/00c3a28820c67c37ebbca72691f4897b57f2eed5/scripts/mysql_secure_installation.sh#L351-L369
+ DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%' ;
+
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
+ FLUSH PRIVILEGES ;
${rootCreate}
DROP DATABASE IF EXISTS test ;
- FLUSH PRIVILEGES ;
EOSQL
- if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then
- mysql+=( -p"${MYSQL_ROOT_PASSWORD}" )
+ # Creates a custom database and user if specified
+ if [ -n "$MYSQL_DATABASE" ]; then
+ mysql_note "Creating database ${MYSQL_DATABASE}"
+ docker_process_sql --database=mysql <<<"CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;"
fi
- file_env 'MYSQL_DATABASE'
- if [ "$MYSQL_DATABASE" ]; then
- echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}"
- mysql+=( "$MYSQL_DATABASE" )
- fi
+ if [ -n "$MYSQL_USER" ] && [ -n "$MYSQL_PASSWORD" ]; then
+ mysql_note "Creating user ${MYSQL_USER}"
+ docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;"
- file_env 'MYSQL_USER'
- file_env 'MYSQL_PASSWORD'
- if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then
- echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}"
+ if [ -n "$MYSQL_DATABASE" ]; then
+ mysql_note "Giving user ${MYSQL_USER} access to schema ${MYSQL_DATABASE}"
+ docker_process_sql --database=mysql <<<"GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;"
+ fi
- if [ "$MYSQL_DATABASE" ]; then
- echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}"
+ docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
+}
+
+_mysql_passfile() {
+ # echo the password to the "file" the client uses
+ # the client command will use process substitution to create a file on the fly
+ # ie: --defaults-file=<( _mysql_passfile )
+ if [ '--dont-use-mysql-root-password' != "$1" ] && [ -n "$MYSQL_ROOT_PASSWORD" ]; then
+ cat <<-EOF
+ [client]
+ password="${MYSQL_ROOT_PASSWORD}"
+ EOF
fi
+}
- echo
- for f in /docker-entrypoint-initdb.d/*; do
- case "$f" in
- *.sh) echo "$0: running $f"; . "$f" ;;
- *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
- *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
- *) echo "$0: ignoring $f" ;;
+# check arguments for an option that would cause mysqld to stop
+# return true if there is one
+_mysql_want_help() {
+ local arg
+ for arg; do
+ case "$arg" in
+ -'?'|--help|--print-defaults|-V|--version)
+ return 0
+ ;;
esac
- echo
done
+ return 1
+}
- if ! kill -s TERM "$pid" || ! wait "$pid"; then
- echo >&2 'MySQL init process failed.'
- exit 1
+_main() {
+ # if command starts with an option, prepend mysqld
+ if [ "${1:0:1}" = '-' ]; then
+ set -- mysqld "$@"
fi
+ # skip setup if they aren't running mysqld or want an option that stops mysqld
+ if [ "$1" = 'mysqld' ] && ! _mysql_want_help "$@"; then
+ mysql_note "Entrypoint script for MySQL Server ${MYSQL_VERSION} started."
+
+ mysql_check_config "$@"
+ # Load various environment variables
+ docker_setup_env "$@"
+ docker_create_db_directories
+
+ # If container is started as root user, restart as dedicated mysql user
+ if [ "$(id -u)" = "0" ]; then
+ mysql_note "Switching to dedicated user 'mysql'"
+ exec gosu mysql "$BASH_SOURCE" "$@"
+ fi
+
+ # there's no database, so it needs to be initialized
+ if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
+ docker_verify_minimum_env
+ docker_init_database_dir "$@"
+
+ mysql_note "Starting temporary server"
+ docker_temp_server_start "$@"
+ mysql_note "Temporary server started."
+
+ docker_setup_db
+ docker_process_init_files /docker-entrypoint-initdb.d/*
+
+ mysql_note "Stopping temporary server"
+ docker_temp_server_stop
+ mysql_note "Temporary server stopped"
+
echo
- echo 'MySQL init process done. Ready for start up.'
+ mysql_note "MySQL init process done. Ready for start up."
echo
fi
-fi
+ fi
+ exec "$@"
+}
-exec "$@"
+# If we are sourced from elsewhere, don't perform any further actions
+if ! _is_sourced; then
+ _main "$@"
+fi
diff --git a/mariadb_10.2/docker-entrypoint.sh b/mariadb_10.2/docker-entrypoint.sh
index 7ee5efd..77c5d4c 100755
--- a/mariadb_10.2/docker-entrypoint.sh
+++ b/mariadb_10.2/docker-entrypoint.sh
@@ -2,21 +2,21 @@
set -eo pipefail
shopt -s nullglob
-# if command starts with an option, prepend mysqld
-if [ "${1:0:1}" = '-' ]; then
- set -- mysqld "$@"
-fi
-
-# skip setup if they want an option that stops mysqld
-wantHelp=
-for arg; do
- case "$arg" in
- -'?'|--help|--print-defaults|-V|--version)
- wantHelp=1
- break
- ;;
- esac
-done
+# logging functions
+mysql_log() {
+ local type="$1"; shift
+ printf '%s [%s] [Entrypoint]: %s\n' "$(date --rfc-3339=seconds)" "$type" "$*"
+}
+mysql_note() {
+ mysql_log Note "$@"
+}
+mysql_warn() {
+ mysql_log Warn "$@" >&2
+}
+mysql_error() {
+ mysql_log ERROR "$@" >&2
+ exit 1
+}
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
@@ -27,8 +27,7 @@ file_env() {
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
+ mysql_error "Both $var and $fileVar are set (but are exclusive)"
fi
local val="$def"
if [ "${!var:-}" ]; then
@@ -40,56 +39,106 @@ file_env() {
unset "$fileVar"
}
-_check_config() {
- toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" )
- if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
- cat >&2 <<-EOM
+# check to see if this file is being run or sourced from another script
+_is_sourced() {
+ # https://unix.stackexchange.com/a/215279
+ [ "${#FUNCNAME[@]}" -ge 2 ] \
+ && [ "${FUNCNAME[0]}" = '_is_sourced' ] \
+ && [ "${FUNCNAME[1]}" = 'source' ]
+}
- ERROR: mysqld failed while attempting to check config
- command was: "${toRun[*]}"
+# usage: docker_process_init_files [file [file [...]]]
+# ie: docker_process_init_files /always-initdb.d/*
+# process initializer files, based on file extensions
+docker_process_init_files() {
+ # mysql here for backwards compatibility "${mysql[@]}"
+ mysql=( docker_process_sql )
- $errors
- EOM
- exit 1
+ echo
+ local f
+ for f; do
+ case "$f" in
+ *.sh) mysql_note "$0: running $f"; . "$f" ;;
+ *.sql) mysql_note "$0: running $f"; docker_process_sql < "$f"; echo ;;
+ *.sql.gz) mysql_note "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;;
+ *) mysql_warn "$0: ignoring $f" ;;
+ esac
+ echo
+ done
+}
+
+mysql_check_config() {
+ local toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" ) errors
+ if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
+ mysql_error $'mysqld failed while attempting to check config\n\tcommand was: '"${toRun[*]}"$'\n\t'"$errors"
fi
}
# Fetch value from server config
# We use mysqld --verbose --help instead of my_print_defaults because the
# latter only show values present in config files, and not server defaults
-_get_config() {
+mysql_get_config() {
local conf="$1"; shift
"$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null \
- | awk '$1 == "'"$conf"'" && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
+ | awk -v conf="$conf" '$1 == conf && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
# match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)"
}
-# allow the container to be started with `--user`
-if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then
- _check_config "$@"
- DATADIR="$(_get_config 'datadir' "$@")"
- mkdir -p "$DATADIR"
- find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
- exec gosu mysql "$BASH_SOURCE" "$@"
-fi
+# Do a temporary startup of the MySQL server, for init purposes
+docker_temp_server_start() {
+ "$@" --skip-networking --socket="${SOCKET}" &
+ mysql_note "Waiting for server startup"
+ local i
+ for i in {30..0}; do
+ # only use the root password if the database has already been initializaed
+ # so that it won't try to fill in a password file when it hasn't been set yet
+ extraArgs=()
+ if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
+ extraArgs+=( '--dont-use-mysql-root-password' )
+ fi
+ if docker_process_sql "${extraArgs[@]}" --database=mysql <<<'SELECT 1' &> /dev/null; then
+ break
+ fi
+ sleep 1
+ done
+ if [ "$i" = 0 ]; then
+ mysql_error "Unable to start server."
+ fi
+}
-if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
- # still need to check config, container may have started with --user
- _check_config "$@"
- # Get config
- DATADIR="$(_get_config 'datadir' "$@")"
+# Stop the server. When using a local socket file mysqladmin will block until
+# the shutdown is complete.
+docker_temp_server_stop() {
+ if ! mysqladmin --defaults-extra-file=<( _mysql_passfile ) shutdown -uroot --socket="${SOCKET}"; then
+ mysql_error "Unable to shut down server."
+ fi
+}
- if [ ! -d "$DATADIR/mysql" ]; then
- file_env 'MYSQL_ROOT_PASSWORD'
+# Verify that the minimally required password settings are set for new databases.
+docker_verify_minimum_env() {
if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
- echo >&2 'error: database is uninitialized and password option is not specified '
- echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
- exit 1
+ mysql_error $'Database is uninitialized and password option is not specified\n\tYou need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
fi
+}
+
+# creates folders for the database
+# also ensures permission for user mysql of run as root
+docker_create_db_directories() {
+ local user; user="$(id -u)"
+ # TODO other directories that are used by default? like /var/lib/mysql-files
+ # see https://github.com/docker-library/mysql/issues/562
mkdir -p "$DATADIR"
- echo 'Initializing database'
+ if [ "$user" = "0" ]; then
+ # this will cause less disk access than `chown -R`
+ find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
+ fi
+}
+
+# initializes the database directory
+docker_init_database_dir() {
+ mysql_note "Initializing database files"
installArgs=( --datadir="$DATADIR" --rpm )
if { mysql_install_db --help || :; } | grep -q -- '--auth-root-authentication-method'; then
# beginning in 10.4.3, install_db uses "socket" which only allows system user root to connect, switch back to "normal" to allow mysql root without a password
@@ -99,40 +148,67 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
fi
# "Other options are passed to mysqld." (so we pass all "mysqld" arguments directly here)
mysql_install_db "${installArgs[@]}" "${@:2}"
- echo 'Database initialized'
+ mysql_note "Database files initialized"
+}
- SOCKET="$(_get_config 'socket' "$@")"
- "$@" --skip-networking --socket="${SOCKET}" &
- pid="$!"
+# Loads various settings that are used elsewhere in the script
+# This should be called after mysql_check_config, but before any other functions
+docker_setup_env() {
+ # Get config
+ declare -g DATADIR SOCKET
+ DATADIR="$(mysql_get_config 'datadir' "$@")"
+ SOCKET="$(mysql_get_config 'socket' "$@")"
- mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )
+ # Initialize values that might be stored in a file
+ file_env 'MYSQL_ROOT_HOST' '%'
+ file_env 'MYSQL_DATABASE'
+ file_env 'MYSQL_USER'
+ file_env 'MYSQL_PASSWORD'
+ file_env 'MYSQL_ROOT_PASSWORD'
- for i in {30..0}; do
- if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then
- break
+ declare -g DATABASE_ALREADY_EXISTS
+ if [ -d "$DATADIR/mysql" ]; then
+ DATABASE_ALREADY_EXISTS='true'
fi
- echo 'MySQL init process in progress...'
- sleep 1
- done
- if [ "$i" = 0 ]; then
- echo >&2 'MySQL init process failed.'
- exit 1
+}
+
+# Execute sql script, passed via stdin
+# usage: docker_process_sql [--dont-use-mysql-root-password] [mysql-cli-args]
+# ie: docker_process_sql --database=mydb <<<'INSERT ...'
+# ie: docker_process_sql --dont-use-mysql-root-password --database=mydb <my-file.sql
+docker_process_sql() {
+ passfileArgs=()
+ if [ '--dont-use-mysql-root-password' = "$1" ]; then
+ passfileArgs+=( "$1" )
+ shift
fi
+ # args sent in can override this db, since they will be later in the command
+ if [ -n "$MYSQL_DATABASE" ]; then
+ set -- --database="$MYSQL_DATABASE" "$@"
+ fi
+
+ mysql --defaults-file=<( _mysql_passfile "${passfileArgs[@]}") --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" "$@"
+}
+# Initializes database with timezone info and root password, plus optional extra db/user
+docker_setup_db() {
+ # Load timezone info into database
if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then
# sed is for https://bugs.mysql.com/bug.php?id=20545
- mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql
+ mysql_tzinfo_to_sql /usr/share/zoneinfo \
+ | sed 's/Local time zone must be set--see zic manual page/FCTY/' \
+ | docker_process_sql --dont-use-mysql-root-password --database=mysql
+ # tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is not set yet
fi
-
- if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
+ # Generate random root password
+ if [ -n "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)"
- echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
+ mysql_note "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
fi
-
- rootCreate=
+ # Sets root password and creates root users for non-localhost hosts
+ local rootCreate=
# default root to listen for connections from anywhere
- file_env 'MYSQL_ROOT_HOST' '%'
- if [ ! -z "$MYSQL_ROOT_HOST" -a "$MYSQL_ROOT_HOST" != 'localhost' ]; then
+ if [ -n "$MYSQL_ROOT_HOST" ] && [ "$MYSQL_ROOT_HOST" != 'localhost' ]; then
# no, we don't care if read finds a terminating character in this heredoc
# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151
read -r -d '' rootCreate <<-EOSQL || true
@@ -141,59 +217,115 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
EOSQL
fi
- "${mysql[@]}" <<-EOSQL
+ # tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is just now being set
+ docker_process_sql --dont-use-mysql-root-password --database=mysql <<-EOSQL
-- What's done in this file shouldn't be replicated
-- or products like mysql-fabric won't work
SET @@SESSION.SQL_LOG_BIN=0;
DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ;
SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ;
+ -- 10.1: https://github.com/MariaDB/server/blob/d925aec1c10cebf6c34825a7de50afe4e630aff4/scripts/mysql_secure_installation.sh#L347-L365
+ -- 10.5: https://github.com/MariaDB/server/blob/00c3a28820c67c37ebbca72691f4897b57f2eed5/scripts/mysql_secure_installation.sh#L351-L369
+ DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%' ;
+
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
+ FLUSH PRIVILEGES ;
${rootCreate}
DROP DATABASE IF EXISTS test ;
- FLUSH PRIVILEGES ;
EOSQL
- if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then
- mysql+=( -p"${MYSQL_ROOT_PASSWORD}" )
+ # Creates a custom database and user if specified
+ if [ -n "$MYSQL_DATABASE" ]; then
+ mysql_note "Creating database ${MYSQL_DATABASE}"
+ docker_process_sql --database=mysql <<<"CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;"
fi
- file_env 'MYSQL_DATABASE'
- if [ "$MYSQL_DATABASE" ]; then
- echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}"
- mysql+=( "$MYSQL_DATABASE" )
- fi
+ if [ -n "$MYSQL_USER" ] && [ -n "$MYSQL_PASSWORD" ]; then
+ mysql_note "Creating user ${MYSQL_USER}"
+ docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;"
- file_env 'MYSQL_USER'
- file_env 'MYSQL_PASSWORD'
- if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then
- echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}"
+ if [ -n "$MYSQL_DATABASE" ]; then
+ mysql_note "Giving user ${MYSQL_USER} access to schema ${MYSQL_DATABASE}"
+ docker_process_sql --database=mysql <<<"GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;"
+ fi
- if [ "$MYSQL_DATABASE" ]; then
- echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}"
+ docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
+}
+
+_mysql_passfile() {
+ # echo the password to the "file" the client uses
+ # the client command will use process substitution to create a file on the fly
+ # ie: --defaults-file=<( _mysql_passfile )
+ if [ '--dont-use-mysql-root-password' != "$1" ] && [ -n "$MYSQL_ROOT_PASSWORD" ]; then
+ cat <<-EOF
+ [client]
+ password="${MYSQL_ROOT_PASSWORD}"
+ EOF
fi
+}
- echo
- for f in /docker-entrypoint-initdb.d/*; do
- case "$f" in
- *.sh) echo "$0: running $f"; . "$f" ;;
- *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
- *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
- *) echo "$0: ignoring $f" ;;
+# check arguments for an option that would cause mysqld to stop
+# return true if there is one
+_mysql_want_help() {
+ local arg
+ for arg; do
+ case "$arg" in
+ -'?'|--help|--print-defaults|-V|--version)
+ return 0
+ ;;
esac
- echo
done
+ return 1
+}
- if ! kill -s TERM "$pid" || ! wait "$pid"; then
- echo >&2 'MySQL init process failed.'
- exit 1
+_main() {
+ # if command starts with an option, prepend mysqld
+ if [ "${1:0:1}" = '-' ]; then
+ set -- mysqld "$@"
fi
+ # skip setup if they aren't running mysqld or want an option that stops mysqld
+ if [ "$1" = 'mysqld' ] && ! _mysql_want_help "$@"; then
+ mysql_note "Entrypoint script for MySQL Server ${MYSQL_VERSION} started."
+
+ mysql_check_config "$@"
+ # Load various environment variables
+ docker_setup_env "$@"
+ docker_create_db_directories
+
+ # If container is started as root user, restart as dedicated mysql user
+ if [ "$(id -u)" = "0" ]; then
+ mysql_note "Switching to dedicated user 'mysql'"
+ exec gosu mysql "$BASH_SOURCE" "$@"
+ fi
+
+ # there's no database, so it needs to be initialized
+ if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
+ docker_verify_minimum_env
+ docker_init_database_dir "$@"
+
+ mysql_note "Starting temporary server"
+ docker_temp_server_start "$@"
+ mysql_note "Temporary server started."
+
+ docker_setup_db
+ docker_process_init_files /docker-entrypoint-initdb.d/*
+
+ mysql_note "Stopping temporary server"
+ docker_temp_server_stop
+ mysql_note "Temporary server stopped"
+
echo
- echo 'MySQL init process done. Ready for start up.'
+ mysql_note "MySQL init process done. Ready for start up."
echo
fi
-fi
+ fi
+ exec "$@"
+}
-exec "$@"
+# If we are sourced from elsewhere, don't perform any further actions
+if ! _is_sourced; then
+ _main "$@"
+fi
diff --git a/mariadb_10.3/docker-entrypoint.sh b/mariadb_10.3/docker-entrypoint.sh
index 7ee5efd..77c5d4c 100755
--- a/mariadb_10.3/docker-entrypoint.sh
+++ b/mariadb_10.3/docker-entrypoint.sh
@@ -2,21 +2,21 @@
set -eo pipefail
shopt -s nullglob
-# if command starts with an option, prepend mysqld
-if [ "${1:0:1}" = '-' ]; then
- set -- mysqld "$@"
-fi
-
-# skip setup if they want an option that stops mysqld
-wantHelp=
-for arg; do
- case "$arg" in
- -'?'|--help|--print-defaults|-V|--version)
- wantHelp=1
- break
- ;;
- esac
-done
+# logging functions
+mysql_log() {
+ local type="$1"; shift
+ printf '%s [%s] [Entrypoint]: %s\n' "$(date --rfc-3339=seconds)" "$type" "$*"
+}
+mysql_note() {
+ mysql_log Note "$@"
+}
+mysql_warn() {
+ mysql_log Warn "$@" >&2
+}
+mysql_error() {
+ mysql_log ERROR "$@" >&2
+ exit 1
+}
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
@@ -27,8 +27,7 @@ file_env() {
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
+ mysql_error "Both $var and $fileVar are set (but are exclusive)"
fi
local val="$def"
if [ "${!var:-}" ]; then
@@ -40,56 +39,106 @@ file_env() {
unset "$fileVar"
}
-_check_config() {
- toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" )
- if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
- cat >&2 <<-EOM
+# check to see if this file is being run or sourced from another script
+_is_sourced() {
+ # https://unix.stackexchange.com/a/215279
+ [ "${#FUNCNAME[@]}" -ge 2 ] \
+ && [ "${FUNCNAME[0]}" = '_is_sourced' ] \
+ && [ "${FUNCNAME[1]}" = 'source' ]
+}
- ERROR: mysqld failed while attempting to check config
- command was: "${toRun[*]}"
+# usage: docker_process_init_files [file [file [...]]]
+# ie: docker_process_init_files /always-initdb.d/*
+# process initializer files, based on file extensions
+docker_process_init_files() {
+ # mysql here for backwards compatibility "${mysql[@]}"
+ mysql=( docker_process_sql )
- $errors
- EOM
- exit 1
+ echo
+ local f
+ for f; do
+ case "$f" in
+ *.sh) mysql_note "$0: running $f"; . "$f" ;;
+ *.sql) mysql_note "$0: running $f"; docker_process_sql < "$f"; echo ;;
+ *.sql.gz) mysql_note "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;;
+ *) mysql_warn "$0: ignoring $f" ;;
+ esac
+ echo
+ done
+}
+
+mysql_check_config() {
+ local toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" ) errors
+ if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
+ mysql_error $'mysqld failed while attempting to check config\n\tcommand was: '"${toRun[*]}"$'\n\t'"$errors"
fi
}
# Fetch value from server config
# We use mysqld --verbose --help instead of my_print_defaults because the
# latter only show values present in config files, and not server defaults
-_get_config() {
+mysql_get_config() {
local conf="$1"; shift
"$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null \
- | awk '$1 == "'"$conf"'" && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
+ | awk -v conf="$conf" '$1 == conf && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
# match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)"
}
-# allow the container to be started with `--user`
-if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then
- _check_config "$@"
- DATADIR="$(_get_config 'datadir' "$@")"
- mkdir -p "$DATADIR"
- find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
- exec gosu mysql "$BASH_SOURCE" "$@"
-fi
+# Do a temporary startup of the MySQL server, for init purposes
+docker_temp_server_start() {
+ "$@" --skip-networking --socket="${SOCKET}" &
+ mysql_note "Waiting for server startup"
+ local i
+ for i in {30..0}; do
+ # only use the root password if the database has already been initializaed
+ # so that it won't try to fill in a password file when it hasn't been set yet
+ extraArgs=()
+ if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
+ extraArgs+=( '--dont-use-mysql-root-password' )
+ fi
+ if docker_process_sql "${extraArgs[@]}" --database=mysql <<<'SELECT 1' &> /dev/null; then
+ break
+ fi
+ sleep 1
+ done
+ if [ "$i" = 0 ]; then
+ mysql_error "Unable to start server."
+ fi
+}
-if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
- # still need to check config, container may have started with --user
- _check_config "$@"
- # Get config
- DATADIR="$(_get_config 'datadir' "$@")"
+# Stop the server. When using a local socket file mysqladmin will block until
+# the shutdown is complete.
+docker_temp_server_stop() {
+ if ! mysqladmin --defaults-extra-file=<( _mysql_passfile ) shutdown -uroot --socket="${SOCKET}"; then
+ mysql_error "Unable to shut down server."
+ fi
+}
- if [ ! -d "$DATADIR/mysql" ]; then
- file_env 'MYSQL_ROOT_PASSWORD'
+# Verify that the minimally required password settings are set for new databases.
+docker_verify_minimum_env() {
if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
- echo >&2 'error: database is uninitialized and password option is not specified '
- echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
- exit 1
+ mysql_error $'Database is uninitialized and password option is not specified\n\tYou need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
fi
+}
+
+# creates folders for the database
+# also ensures permission for user mysql of run as root
+docker_create_db_directories() {
+ local user; user="$(id -u)"
+ # TODO other directories that are used by default? like /var/lib/mysql-files
+ # see https://github.com/docker-library/mysql/issues/562
mkdir -p "$DATADIR"
- echo 'Initializing database'
+ if [ "$user" = "0" ]; then
+ # this will cause less disk access than `chown -R`
+ find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
+ fi
+}
+
+# initializes the database directory
+docker_init_database_dir() {
+ mysql_note "Initializing database files"
installArgs=( --datadir="$DATADIR" --rpm )
if { mysql_install_db --help || :; } | grep -q -- '--auth-root-authentication-method'; then
# beginning in 10.4.3, install_db uses "socket" which only allows system user root to connect, switch back to "normal" to allow mysql root without a password
@@ -99,40 +148,67 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
fi
# "Other options are passed to mysqld." (so we pass all "mysqld" arguments directly here)
mysql_install_db "${installArgs[@]}" "${@:2}"
- echo 'Database initialized'
+ mysql_note "Database files initialized"
+}
- SOCKET="$(_get_config 'socket' "$@")"
- "$@" --skip-networking --socket="${SOCKET}" &
- pid="$!"
+# Loads various settings that are used elsewhere in the script
+# This should be called after mysql_check_config, but before any other functions
+docker_setup_env() {
+ # Get config
+ declare -g DATADIR SOCKET
+ DATADIR="$(mysql_get_config 'datadir' "$@")"
+ SOCKET="$(mysql_get_config 'socket' "$@")"
- mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )
+ # Initialize values that might be stored in a file
+ file_env 'MYSQL_ROOT_HOST' '%'
+ file_env 'MYSQL_DATABASE'
+ file_env 'MYSQL_USER'
+ file_env 'MYSQL_PASSWORD'
+ file_env 'MYSQL_ROOT_PASSWORD'
- for i in {30..0}; do
- if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then
- break
+ declare -g DATABASE_ALREADY_EXISTS
+ if [ -d "$DATADIR/mysql" ]; then
+ DATABASE_ALREADY_EXISTS='true'
fi
- echo 'MySQL init process in progress...'
- sleep 1
- done
- if [ "$i" = 0 ]; then
- echo >&2 'MySQL init process failed.'
- exit 1
+}
+
+# Execute sql script, passed via stdin
+# usage: docker_process_sql [--dont-use-mysql-root-password] [mysql-cli-args]
+# ie: docker_process_sql --database=mydb <<<'INSERT ...'
+# ie: docker_process_sql --dont-use-mysql-root-password --database=mydb <my-file.sql
+docker_process_sql() {
+ passfileArgs=()
+ if [ '--dont-use-mysql-root-password' = "$1" ]; then
+ passfileArgs+=( "$1" )
+ shift
fi
+ # args sent in can override this db, since they will be later in the command
+ if [ -n "$MYSQL_DATABASE" ]; then
+ set -- --database="$MYSQL_DATABASE" "$@"
+ fi
+
+ mysql --defaults-file=<( _mysql_passfile "${passfileArgs[@]}") --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" "$@"
+}
+# Initializes database with timezone info and root password, plus optional extra db/user
+docker_setup_db() {
+ # Load timezone info into database
if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then
# sed is for https://bugs.mysql.com/bug.php?id=20545
- mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql
+ mysql_tzinfo_to_sql /usr/share/zoneinfo \
+ | sed 's/Local time zone must be set--see zic manual page/FCTY/' \
+ | docker_process_sql --dont-use-mysql-root-password --database=mysql
+ # tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is not set yet
fi
-
- if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
+ # Generate random root password
+ if [ -n "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)"
- echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
+ mysql_note "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
fi
-
- rootCreate=
+ # Sets root password and creates root users for non-localhost hosts
+ local rootCreate=
# default root to listen for connections from anywhere
- file_env 'MYSQL_ROOT_HOST' '%'
- if [ ! -z "$MYSQL_ROOT_HOST" -a "$MYSQL_ROOT_HOST" != 'localhost' ]; then
+ if [ -n "$MYSQL_ROOT_HOST" ] && [ "$MYSQL_ROOT_HOST" != 'localhost' ]; then
# no, we don't care if read finds a terminating character in this heredoc
# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151
read -r -d '' rootCreate <<-EOSQL || true
@@ -141,59 +217,115 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
EOSQL
fi
- "${mysql[@]}" <<-EOSQL
+ # tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is just now being set
+ docker_process_sql --dont-use-mysql-root-password --database=mysql <<-EOSQL
-- What's done in this file shouldn't be replicated
-- or products like mysql-fabric won't work
SET @@SESSION.SQL_LOG_BIN=0;
DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ;
SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ;
+ -- 10.1: https://github.com/MariaDB/server/blob/d925aec1c10cebf6c34825a7de50afe4e630aff4/scripts/mysql_secure_installation.sh#L347-L365
+ -- 10.5: https://github.com/MariaDB/server/blob/00c3a28820c67c37ebbca72691f4897b57f2eed5/scripts/mysql_secure_installation.sh#L351-L369
+ DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%' ;
+
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
+ FLUSH PRIVILEGES ;
${rootCreate}
DROP DATABASE IF EXISTS test ;
- FLUSH PRIVILEGES ;
EOSQL
- if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then
- mysql+=( -p"${MYSQL_ROOT_PASSWORD}" )
+ # Creates a custom database and user if specified
+ if [ -n "$MYSQL_DATABASE" ]; then
+ mysql_note "Creating database ${MYSQL_DATABASE}"
+ docker_process_sql --database=mysql <<<"CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;"
fi
- file_env 'MYSQL_DATABASE'
- if [ "$MYSQL_DATABASE" ]; then
- echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}"
- mysql+=( "$MYSQL_DATABASE" )
- fi
+ if [ -n "$MYSQL_USER" ] && [ -n "$MYSQL_PASSWORD" ]; then
+ mysql_note "Creating user ${MYSQL_USER}"
+ docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;"
- file_env 'MYSQL_USER'
- file_env 'MYSQL_PASSWORD'
- if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then
- echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}"
+ if [ -n "$MYSQL_DATABASE" ]; then
+ mysql_note "Giving user ${MYSQL_USER} access to schema ${MYSQL_DATABASE}"
+ docker_process_sql --database=mysql <<<"GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;"
+ fi
- if [ "$MYSQL_DATABASE" ]; then
- echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}"
+ docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
+}
+
+_mysql_passfile() {
+ # echo the password to the "file" the client uses
+ # the client command will use process substitution to create a file on the fly
+ # ie: --defaults-file=<( _mysql_passfile )
+ if [ '--dont-use-mysql-root-password' != "$1" ] && [ -n "$MYSQL_ROOT_PASSWORD" ]; then
+ cat <<-EOF
+ [client]
+ password="${MYSQL_ROOT_PASSWORD}"
+ EOF
fi
+}
- echo
- for f in /docker-entrypoint-initdb.d/*; do
- case "$f" in
- *.sh) echo "$0: running $f"; . "$f" ;;
- *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
- *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
- *) echo "$0: ignoring $f" ;;
+# check arguments for an option that would cause mysqld to stop
+# return true if there is one
+_mysql_want_help() {
+ local arg
+ for arg; do
+ case "$arg" in
+ -'?'|--help|--print-defaults|-V|--version)
+ return 0
+ ;;
esac
- echo
done
+ return 1
+}
- if ! kill -s TERM "$pid" || ! wait "$pid"; then
- echo >&2 'MySQL init process failed.'
- exit 1
+_main() {
+ # if command starts with an option, prepend mysqld
+ if [ "${1:0:1}" = '-' ]; then
+ set -- mysqld "$@"
fi
+ # skip setup if they aren't running mysqld or want an option that stops mysqld
+ if [ "$1" = 'mysqld' ] && ! _mysql_want_help "$@"; then
+ mysql_note "Entrypoint script for MySQL Server ${MYSQL_VERSION} started."
+
+ mysql_check_config "$@"
+ # Load various environment variables
+ docker_setup_env "$@"
+ docker_create_db_directories
+
+ # If container is started as root user, restart as dedicated mysql user
+ if [ "$(id -u)" = "0" ]; then
+ mysql_note "Switching to dedicated user 'mysql'"
+ exec gosu mysql "$BASH_SOURCE" "$@"
+ fi
+
+ # there's no database, so it needs to be initialized
+ if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
+ docker_verify_minimum_env
+ docker_init_database_dir "$@"
+
+ mysql_note "Starting temporary server"
+ docker_temp_server_start "$@"
+ mysql_note "Temporary server started."
+
+ docker_setup_db
+ docker_process_init_files /docker-entrypoint-initdb.d/*
+
+ mysql_note "Stopping temporary server"
+ docker_temp_server_stop
+ mysql_note "Temporary server stopped"
+
echo
- echo 'MySQL init process done. Ready for start up.'
+ mysql_note "MySQL init process done. Ready for start up."
echo
fi
-fi
+ fi
+ exec "$@"
+}
-exec "$@"
+# If we are sourced from elsewhere, don't perform any further actions
+if ! _is_sourced; then
+ _main "$@"
+fi
diff --git a/mariadb_latest/docker-entrypoint.sh b/mariadb_latest/docker-entrypoint.sh
index 7ee5efd..77c5d4c 100755
--- a/mariadb_latest/docker-entrypoint.sh
+++ b/mariadb_latest/docker-entrypoint.sh
@@ -2,21 +2,21 @@
set -eo pipefail
shopt -s nullglob
-# if command starts with an option, prepend mysqld
-if [ "${1:0:1}" = '-' ]; then
- set -- mysqld "$@"
-fi
-
-# skip setup if they want an option that stops mysqld
-wantHelp=
-for arg; do
- case "$arg" in
- -'?'|--help|--print-defaults|-V|--version)
- wantHelp=1
- break
- ;;
- esac
-done
+# logging functions
+mysql_log() {
+ local type="$1"; shift
+ printf '%s [%s] [Entrypoint]: %s\n' "$(date --rfc-3339=seconds)" "$type" "$*"
+}
+mysql_note() {
+ mysql_log Note "$@"
+}
+mysql_warn() {
+ mysql_log Warn "$@" >&2
+}
+mysql_error() {
+ mysql_log ERROR "$@" >&2
+ exit 1
+}
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
@@ -27,8 +27,7 @@ file_env() {
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
+ mysql_error "Both $var and $fileVar are set (but are exclusive)"
fi
local val="$def"
if [ "${!var:-}" ]; then
@@ -40,56 +39,106 @@ file_env() {
unset "$fileVar"
}
-_check_config() {
- toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" )
- if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
- cat >&2 <<-EOM
+# check to see if this file is being run or sourced from another script
+_is_sourced() {
+ # https://unix.stackexchange.com/a/215279
+ [ "${#FUNCNAME[@]}" -ge 2 ] \
+ && [ "${FUNCNAME[0]}" = '_is_sourced' ] \
+ && [ "${FUNCNAME[1]}" = 'source' ]
+}
- ERROR: mysqld failed while attempting to check config
- command was: "${toRun[*]}"
+# usage: docker_process_init_files [file [file [...]]]
+# ie: docker_process_init_files /always-initdb.d/*
+# process initializer files, based on file extensions
+docker_process_init_files() {
+ # mysql here for backwards compatibility "${mysql[@]}"
+ mysql=( docker_process_sql )
- $errors
- EOM
- exit 1
+ echo
+ local f
+ for f; do
+ case "$f" in
+ *.sh) mysql_note "$0: running $f"; . "$f" ;;
+ *.sql) mysql_note "$0: running $f"; docker_process_sql < "$f"; echo ;;
+ *.sql.gz) mysql_note "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;;
+ *) mysql_warn "$0: ignoring $f" ;;
+ esac
+ echo
+ done
+}
+
+mysql_check_config() {
+ local toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" ) errors
+ if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
+ mysql_error $'mysqld failed while attempting to check config\n\tcommand was: '"${toRun[*]}"$'\n\t'"$errors"
fi
}
# Fetch value from server config
# We use mysqld --verbose --help instead of my_print_defaults because the
# latter only show values present in config files, and not server defaults
-_get_config() {
+mysql_get_config() {
local conf="$1"; shift
"$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null \
- | awk '$1 == "'"$conf"'" && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
+ | awk -v conf="$conf" '$1 == conf && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }'
# match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)"
}
-# allow the container to be started with `--user`
-if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then
- _check_config "$@"
- DATADIR="$(_get_config 'datadir' "$@")"
- mkdir -p "$DATADIR"
- find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
- exec gosu mysql "$BASH_SOURCE" "$@"
-fi
+# Do a temporary startup of the MySQL server, for init purposes
+docker_temp_server_start() {
+ "$@" --skip-networking --socket="${SOCKET}" &
+ mysql_note "Waiting for server startup"
+ local i
+ for i in {30..0}; do
+ # only use the root password if the database has already been initializaed
+ # so that it won't try to fill in a password file when it hasn't been set yet
+ extraArgs=()
+ if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
+ extraArgs+=( '--dont-use-mysql-root-password' )
+ fi
+ if docker_process_sql "${extraArgs[@]}" --database=mysql <<<'SELECT 1' &> /dev/null; then
+ break
+ fi
+ sleep 1
+ done
+ if [ "$i" = 0 ]; then
+ mysql_error "Unable to start server."
+ fi
+}
-if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
- # still need to check config, container may have started with --user
- _check_config "$@"
- # Get config
- DATADIR="$(_get_config 'datadir' "$@")"
+# Stop the server. When using a local socket file mysqladmin will block until
+# the shutdown is complete.
+docker_temp_server_stop() {
+ if ! mysqladmin --defaults-extra-file=<( _mysql_passfile ) shutdown -uroot --socket="${SOCKET}"; then
+ mysql_error "Unable to shut down server."
+ fi
+}
- if [ ! -d "$DATADIR/mysql" ]; then
- file_env 'MYSQL_ROOT_PASSWORD'
+# Verify that the minimally required password settings are set for new databases.
+docker_verify_minimum_env() {
if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
- echo >&2 'error: database is uninitialized and password option is not specified '
- echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
- exit 1
+ mysql_error $'Database is uninitialized and password option is not specified\n\tYou need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
fi
+}
+
+# creates folders for the database
+# also ensures permission for user mysql of run as root
+docker_create_db_directories() {
+ local user; user="$(id -u)"
+ # TODO other directories that are used by default? like /var/lib/mysql-files
+ # see https://github.com/docker-library/mysql/issues/562
mkdir -p "$DATADIR"
- echo 'Initializing database'
+ if [ "$user" = "0" ]; then
+ # this will cause less disk access than `chown -R`
+ find "$DATADIR" \! -user mysql -exec chown mysql '{}' +
+ fi
+}
+
+# initializes the database directory
+docker_init_database_dir() {
+ mysql_note "Initializing database files"
installArgs=( --datadir="$DATADIR" --rpm )
if { mysql_install_db --help || :; } | grep -q -- '--auth-root-authentication-method'; then
# beginning in 10.4.3, install_db uses "socket" which only allows system user root to connect, switch back to "normal" to allow mysql root without a password
@@ -99,40 +148,67 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
fi
# "Other options are passed to mysqld." (so we pass all "mysqld" arguments directly here)
mysql_install_db "${installArgs[@]}" "${@:2}"
- echo 'Database initialized'
+ mysql_note "Database files initialized"
+}
- SOCKET="$(_get_config 'socket' "$@")"
- "$@" --skip-networking --socket="${SOCKET}" &
- pid="$!"
+# Loads various settings that are used elsewhere in the script
+# This should be called after mysql_check_config, but before any other functions
+docker_setup_env() {
+ # Get config
+ declare -g DATADIR SOCKET
+ DATADIR="$(mysql_get_config 'datadir' "$@")"
+ SOCKET="$(mysql_get_config 'socket' "$@")"
- mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )
+ # Initialize values that might be stored in a file
+ file_env 'MYSQL_ROOT_HOST' '%'
+ file_env 'MYSQL_DATABASE'
+ file_env 'MYSQL_USER'
+ file_env 'MYSQL_PASSWORD'
+ file_env 'MYSQL_ROOT_PASSWORD'
- for i in {30..0}; do
- if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then
- break
+ declare -g DATABASE_ALREADY_EXISTS
+ if [ -d "$DATADIR/mysql" ]; then
+ DATABASE_ALREADY_EXISTS='true'
fi
- echo 'MySQL init process in progress...'
- sleep 1
- done
- if [ "$i" = 0 ]; then
- echo >&2 'MySQL init process failed.'
- exit 1
+}
+
+# Execute sql script, passed via stdin
+# usage: docker_process_sql [--dont-use-mysql-root-password] [mysql-cli-args]
+# ie: docker_process_sql --database=mydb <<<'INSERT ...'
+# ie: docker_process_sql --dont-use-mysql-root-password --database=mydb <my-file.sql
+docker_process_sql() {
+ passfileArgs=()
+ if [ '--dont-use-mysql-root-password' = "$1" ]; then
+ passfileArgs+=( "$1" )
+ shift
fi
+ # args sent in can override this db, since they will be later in the command
+ if [ -n "$MYSQL_DATABASE" ]; then
+ set -- --database="$MYSQL_DATABASE" "$@"
+ fi
+
+ mysql --defaults-file=<( _mysql_passfile "${passfileArgs[@]}") --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" "$@"
+}
+# Initializes database with timezone info and root password, plus optional extra db/user
+docker_setup_db() {
+ # Load timezone info into database
if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then
# sed is for https://bugs.mysql.com/bug.php?id=20545
- mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql
+ mysql_tzinfo_to_sql /usr/share/zoneinfo \
+ | sed 's/Local time zone must be set--see zic manual page/FCTY/' \
+ | docker_process_sql --dont-use-mysql-root-password --database=mysql
+ # tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is not set yet
fi
-
- if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
+ # Generate random root password
+ if [ -n "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)"
- echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
+ mysql_note "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
fi
-
- rootCreate=
+ # Sets root password and creates root users for non-localhost hosts
+ local rootCreate=
# default root to listen for connections from anywhere
- file_env 'MYSQL_ROOT_HOST' '%'
- if [ ! -z "$MYSQL_ROOT_HOST" -a "$MYSQL_ROOT_HOST" != 'localhost' ]; then
+ if [ -n "$MYSQL_ROOT_HOST" ] && [ "$MYSQL_ROOT_HOST" != 'localhost' ]; then
# no, we don't care if read finds a terminating character in this heredoc
# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151
read -r -d '' rootCreate <<-EOSQL || true
@@ -141,59 +217,115 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
EOSQL
fi
- "${mysql[@]}" <<-EOSQL
+ # tell docker_process_sql to not use MYSQL_ROOT_PASSWORD since it is just now being set
+ docker_process_sql --dont-use-mysql-root-password --database=mysql <<-EOSQL
-- What's done in this file shouldn't be replicated
-- or products like mysql-fabric won't work
SET @@SESSION.SQL_LOG_BIN=0;
DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ;
SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ;
+ -- 10.1: https://github.com/MariaDB/server/blob/d925aec1c10cebf6c34825a7de50afe4e630aff4/scripts/mysql_secure_installation.sh#L347-L365
+ -- 10.5: https://github.com/MariaDB/server/blob/00c3a28820c67c37ebbca72691f4897b57f2eed5/scripts/mysql_secure_installation.sh#L351-L369
+ DELETE FROM mysql.db WHERE Db='test' OR Db='test\_%' ;
+
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
+ FLUSH PRIVILEGES ;
${rootCreate}
DROP DATABASE IF EXISTS test ;
- FLUSH PRIVILEGES ;
EOSQL
- if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then
- mysql+=( -p"${MYSQL_ROOT_PASSWORD}" )
+ # Creates a custom database and user if specified
+ if [ -n "$MYSQL_DATABASE" ]; then
+ mysql_note "Creating database ${MYSQL_DATABASE}"
+ docker_process_sql --database=mysql <<<"CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;"
fi
- file_env 'MYSQL_DATABASE'
- if [ "$MYSQL_DATABASE" ]; then
- echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}"
- mysql+=( "$MYSQL_DATABASE" )
- fi
+ if [ -n "$MYSQL_USER" ] && [ -n "$MYSQL_PASSWORD" ]; then
+ mysql_note "Creating user ${MYSQL_USER}"
+ docker_process_sql --database=mysql <<<"CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;"
- file_env 'MYSQL_USER'
- file_env 'MYSQL_PASSWORD'
- if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then
- echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}"
+ if [ -n "$MYSQL_DATABASE" ]; then
+ mysql_note "Giving user ${MYSQL_USER} access to schema ${MYSQL_DATABASE}"
+ docker_process_sql --database=mysql <<<"GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;"
+ fi
- if [ "$MYSQL_DATABASE" ]; then
- echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}"
+ docker_process_sql --database=mysql <<<"FLUSH PRIVILEGES ;"
fi
+}
+
+_mysql_passfile() {
+ # echo the password to the "file" the client uses
+ # the client command will use process substitution to create a file on the fly
+ # ie: --defaults-file=<( _mysql_passfile )
+ if [ '--dont-use-mysql-root-password' != "$1" ] && [ -n "$MYSQL_ROOT_PASSWORD" ]; then
+ cat <<-EOF
+ [client]
+ password="${MYSQL_ROOT_PASSWORD}"
+ EOF
fi
+}
- echo
- for f in /docker-entrypoint-initdb.d/*; do
- case "$f" in
- *.sh) echo "$0: running $f"; . "$f" ;;
- *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
- *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
- *) echo "$0: ignoring $f" ;;
+# check arguments for an option that would cause mysqld to stop
+# return true if there is one
+_mysql_want_help() {
+ local arg
+ for arg; do
+ case "$arg" in
+ -'?'|--help|--print-defaults|-V|--version)
+ return 0
+ ;;
esac
- echo
done
+ return 1
+}
- if ! kill -s TERM "$pid" || ! wait "$pid"; then
- echo >&2 'MySQL init process failed.'
- exit 1
+_main() {
+ # if command starts with an option, prepend mysqld
+ if [ "${1:0:1}" = '-' ]; then
+ set -- mysqld "$@"
fi
+ # skip setup if they aren't running mysqld or want an option that stops mysqld
+ if [ "$1" = 'mysqld' ] && ! _mysql_want_help "$@"; then
+ mysql_note "Entrypoint script for MySQL Server ${MYSQL_VERSION} started."
+
+ mysql_check_config "$@"
+ # Load various environment variables
+ docker_setup_env "$@"
+ docker_create_db_directories
+
+ # If container is started as root user, restart as dedicated mysql user
+ if [ "$(id -u)" = "0" ]; then
+ mysql_note "Switching to dedicated user 'mysql'"
+ exec gosu mysql "$BASH_SOURCE" "$@"
+ fi
+
+ # there's no database, so it needs to be initialized
+ if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
+ docker_verify_minimum_env
+ docker_init_database_dir "$@"
+
+ mysql_note "Starting temporary server"
+ docker_temp_server_start "$@"
+ mysql_note "Temporary server started."
+
+ docker_setup_db
+ docker_process_init_files /docker-entrypoint-initdb.d/*
+
+ mysql_note "Stopping temporary server"
+ docker_temp_server_stop
+ mysql_note "Temporary server stopped"
+
echo
- echo 'MySQL init process done. Ready for start up.'
+ mysql_note "MySQL init process done. Ready for start up."
echo
fi
-fi
+ fi
+ exec "$@"
+}
-exec "$@"
+# If we are sourced from elsewhere, don't perform any further actions
+if ! _is_sourced; then
+ _main "$@"
+fi |
Build test of #6965; 5026d50; $ bashbrew build mariadb:10.4.10-bionic
Building bashbrew/cache:68217c6a61a230e094f80e664189b34d6ad4de2c052fac97cfeb07417ee980c8 (mariadb:10.4.10-bionic)
Tagging mariadb:10.4.10-bionic
Tagging mariadb:10.4-bionic
Tagging mariadb:10-bionic
Tagging mariadb:bionic
Tagging mariadb:10.4.10
Tagging mariadb:10.4
Tagging mariadb:10
Tagging mariadb:latest
$ test/run.sh mariadb:10.4.10-bionic
testing mariadb:10.4.10-bionic
'utc' [1/7]...passed
'cve-2014--shellshock' [2/7]...passed
'no-hard-coded-passwords' [3/7]...passed
'override-cmd' [4/7]...passed
'mysql-basics' [5/7].........passed
'mysql-initdb' [6/7].........passed
'mysql-log-bin' [7/7].........passed
$ bashbrew build mariadb:10.3.20-bionic
Building bashbrew/cache:59d578f7e9a229477460875392a079ccca442e69c38518a1ed19933087490b25 (mariadb:10.3.20-bionic)
Tagging mariadb:10.3.20-bionic
Tagging mariadb:10.3-bionic
Tagging mariadb:10.3.20
Tagging mariadb:10.3
$ test/run.sh mariadb:10.3.20-bionic
testing mariadb:10.3.20-bionic
'utc' [1/7]...passed
'cve-2014--shellshock' [2/7]...passed
'no-hard-coded-passwords' [3/7]...passed
'override-cmd' [4/7]...passed
'mysql-basics' [5/7].........passed
'mysql-initdb' [6/7].........passed
'mysql-log-bin' [7/7].........passed
$ bashbrew build mariadb:10.2.29-bionic
Building bashbrew/cache:03451b5f833c53b3488efb2426f8a8efa33b6baa9442429c577b784c435bc709 (mariadb:10.2.29-bionic)
Tagging mariadb:10.2.29-bionic
Tagging mariadb:10.2-bionic
Tagging mariadb:10.2.29
Tagging mariadb:10.2
$ test/run.sh mariadb:10.2.29-bionic
testing mariadb:10.2.29-bionic
'utc' [1/7]...passed
'cve-2014--shellshock' [2/7]...passed
'no-hard-coded-passwords' [3/7]...passed
'override-cmd' [4/7]...passed
'mysql-basics' [5/7].........passed
'mysql-initdb' [6/7].........passed
'mysql-log-bin' [7/7].........passed
$ bashbrew build mariadb:10.1.43-bionic
Building bashbrew/cache:2cd60c22b4e734355c71ef400bcd4b9a9dc21a5beb1b11bdfbe836e835a7c5be (mariadb:10.1.43-bionic)
Tagging mariadb:10.1.43-bionic
Tagging mariadb:10.1-bionic
Tagging mariadb:10.1.43
Tagging mariadb:10.1
$ test/run.sh mariadb:10.1.43-bionic
testing mariadb:10.1.43-bionic
'utc' [1/7]...passed
'cve-2014--shellshock' [2/7]...passed
'no-hard-coded-passwords' [3/7]...passed
'override-cmd' [4/7]...passed
'mysql-basics' [5/7]...........passed
'mysql-initdb' [6/7]...........passed
'mysql-log-bin' [7/7]...........passed
|
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Changes: