From b81afa129cad5113c1c570d6d400abc6de36d194 Mon Sep 17 00:00:00 2001 From: Daniel Dolezal Date: Mon, 7 Apr 2025 00:38:38 +0200 Subject: [PATCH] updaate docker-entrypoint file --- scripts/docker-entrypoint.sh | 301 ++++++++++++++++++++++++++++------- 1 file changed, 240 insertions(+), 61 deletions(-) diff --git a/scripts/docker-entrypoint.sh b/scripts/docker-entrypoint.sh index b298f14..7538708 100755 --- a/scripts/docker-entrypoint.sh +++ b/scripts/docker-entrypoint.sh @@ -121,7 +121,10 @@ mysql_get_config() { docker_temp_server_start() { "$@" --skip-networking --default-time-zone=SYSTEM --socket="${SOCKET}" --wsrep_on=OFF \ --expire-logs-days=0 \ - --loose-innodb_buffer_pool_load_at_startup=0 & + --skip-slave-start \ + --loose-innodb_buffer_pool_load_at_startup=0 \ + --skip-ssl --ssl-cert='' --ssl-key='' --ssl-ca='' \ + & declare -g MARIADB_PID MARIADB_PID=$! mysql_note "Waiting for server startup" @@ -133,7 +136,9 @@ docker_temp_server_start() { fi local i for i in {30..0}; do - if docker_process_sql "${extraArgs[@]}" --database=mysql <<<'SELECT 1' &> /dev/null; then + if docker_process_sql "${extraArgs[@]}" --database=mysql \ + --skip-ssl --skip-ssl-verify-server-cert \ + <<<'SELECT 1' &> /dev/null; then break fi sleep 1 @@ -152,6 +157,14 @@ docker_temp_server_stop() { # Verify that the minimally required password settings are set for new databases. docker_verify_minimum_env() { + # Restoring from backup requires no environment variables + declare -g DATABASE_INIT_FROM_BACKUP + for file in /docker-entrypoint-initdb.d/*.tar{.gz,.xz,.zst}; do + if [ -f "${file}" ]; then + DATABASE_INIT_FROM_BACKUP='true' + return + fi + done if [ -z "$MARIADB_ROOT_PASSWORD" ] && [ -z "$MARIADB_ROOT_PASSWORD_HASH" ] && [ -z "$MARIADB_ALLOW_EMPTY_ROOT_PASSWORD" ] && [ -z "$MARIADB_RANDOM_ROOT_PASSWORD" ]; then mysql_error $'Database is uninitialized and password option is not specified\n\tYou need to specify one of MARIADB_ROOT_PASSWORD, MARIADB_ROOT_PASSWORD_HASH, MARIADB_ALLOW_EMPTY_ROOT_PASSWORD and MARIADB_RANDOM_ROOT_PASSWORD' fi @@ -162,6 +175,25 @@ docker_verify_minimum_env() { if [ -n "$MARIADB_PASSWORD" ] && [ -n "$MARIADB_PASSWORD_HASH" ]; then mysql_error "Cannot specify MARIADB_PASSWORD_HASH and MARIADB_PASSWORD option." fi + if [ -n "$MARIADB_REPLICATION_USER" ]; then + if [ -z "$MARIADB_MASTER_HOST" ]; then + # its a master, we're creating a user + if [ -z "$MARIADB_REPLICATION_PASSWORD" ] && [ -z "$MARIADB_REPLICATION_PASSWORD_HASH" ]; then + mysql_error "MARIADB_REPLICATION_PASSWORD or MARIADB_REPLICATION_PASSWORD_HASH not found to create replication user for master" + fi + else + # its a replica + if [ -z "$MARIADB_REPLICATION_PASSWORD" ] ; then + mysql_error "MARIADB_REPLICATION_PASSWORD is mandatory to specify the replication on the replica image." + fi + if [ -n "$MARIADB_REPLICATION_PASSWORD_HASH" ] ; then + mysql_warn "MARIADB_REPLICATION_PASSWORD_HASH cannot be specified on a replica" + fi + fi + fi + if [ -n "$MARIADB_MASTER_HOST" ] && { [ -z "$MARIADB_REPLICATION_USER" ] || [ -z "$MARIADB_REPLICATION_PASSWORD" ] ; }; then + mysql_error "For a replica, MARIADB_REPLICATION_USER and MARIADB_REPLICATION is mandatory." + fi } # creates folders for the database @@ -175,25 +207,46 @@ docker_create_db_directories() { if [ "$user" = "0" ]; then # this will cause less disk access than `chown -R` - find "$DATADIR" \! -user mysql -exec chown mysql: '{}' + + find "$DATADIR" \! -user mysql \( -exec chown mysql: '{}' + -o -true \) # See https://github.com/MariaDB/mariadb-docker/issues/363 - find "${SOCKET%/*}" -maxdepth 0 \! -user mysql -exec chown mysql: '{}' \; + if [ "${SOCKET:0:1}" != '@' ]; then # not abstract sockets + find "${SOCKET%/*}" -maxdepth 0 \! -user mysql \( -exec chown mysql: '{}' \; -o -true \) + fi + + # memory.pressure + local cgroup; cgroup=$( "$DATADIR"/.my-healthcheck.cnf + $maskPreserve +} + # Initializes database with timezone info and root password, plus optional extra db/user docker_setup_db() { # Load timezone info into database @@ -289,7 +386,7 @@ docker_setup_db() { local rootPasswordEscaped= if [ -n "$MARIADB_ROOT_PASSWORD" ]; then # Sets root password and creates root users for non-localhost hosts - rootPasswordEscaped=$( docker_sql_escape_string_literal "${MARIADB_ROOT_PASSWORD}" ) + rootPasswordEscaped=$(docker_sql_escape_string_literal "${MARIADB_ROOT_PASSWORD}") fi # default root to listen for connections from anywhere @@ -300,11 +397,13 @@ docker_setup_db() { read -r -d '' rootCreate <<-EOSQL || true CREATE USER 'root'@'${MARIADB_ROOT_HOST}' IDENTIFIED BY PASSWORD '${MARIADB_ROOT_PASSWORD_HASH}' ; GRANT ALL ON *.* TO 'root'@'${MARIADB_ROOT_HOST}' WITH GRANT OPTION ; + GRANT PROXY ON ''@'%' TO 'root'@'${MARIADB_ROOT_HOST}' WITH GRANT OPTION; EOSQL else read -r -d '' rootCreate <<-EOSQL || true CREATE USER 'root'@'${MARIADB_ROOT_HOST}' IDENTIFIED BY '${rootPasswordEscaped}' ; GRANT ALL ON *.* TO 'root'@'${MARIADB_ROOT_HOST}' WITH GRANT OPTION ; + GRANT PROXY ON ''@'%' TO 'root'@'${MARIADB_ROOT_HOST}' WITH GRANT OPTION; EOSQL fi fi @@ -313,16 +412,8 @@ docker_setup_db() { local mysqlAtLocalhostGrants= # Install mysql@localhost user if [ -n "$MARIADB_MYSQL_LOCALHOST_USER" ]; then - local pw= - pw="$(pwgen --numerals --capitalize --symbols --remove-chars="'\\" -1 32)" - # MDEV-24111 before MariaDB-10.4 cannot create unix_socket user directly auth with simple_password_check - # It wasn't until 10.4 that the unix_socket auth was built in to the server. read -r -d '' mysqlAtLocalhost <<-EOSQL || true - EXECUTE IMMEDIATE IF(VERSION() RLIKE '^10\.3\.', - "INSTALL PLUGIN /*M10401 IF NOT EXISTS */ unix_socket SONAME 'auth_socket'", - "SELECT 'already there'"); - CREATE USER mysql@localhost IDENTIFIED BY '$pw'; - ALTER USER mysql@localhost IDENTIFIED VIA unix_socket; + CREATE USER mysql@localhost IDENTIFIED VIA unix_socket; EOSQL if [ -n "$MARIADB_MYSQL_LOCALHOST_GRANTS" ]; then if [ "$MARIADB_MYSQL_LOCALHOST_GRANTS" != USAGE ]; then @@ -332,6 +423,9 @@ docker_setup_db() { fi fi + local createHealthCheckUsers + createHealthCheckUsers=$(create_healthcheck_users) + local rootLocalhostPass= if [ -z "$MARIADB_ROOT_PASSWORD_HASH" ]; then # handle MARIADB_ROOT_PASSWORD_HASH for root@localhost after /docker-entrypoint-initdb.d @@ -354,7 +448,7 @@ docker_setup_db() { else # SQL escape the user password, \ followed by ' local userPasswordEscaped - userPasswordEscaped=$( docker_sql_escape_string_literal "${MARIADB_PASSWORD}" ) + userPasswordEscaped=$(docker_sql_escape_string_literal "${MARIADB_PASSWORD}") createUser="CREATE USER '$MARIADB_USER'@'%' IDENTIFIED BY '$userPasswordEscaped';" fi @@ -364,6 +458,24 @@ docker_setup_db() { fi fi + # To create replica user + local createReplicaUser= + local changeMasterTo= + if [ -n "$MARIADB_REPLICATION_USER" ] ; then + if [ -z "$MARIADB_MASTER_HOST" ]; then + # on master + mysql_note "Creating user ${MARIADB_REPLICATION_USER}" + createReplicaUser=$(create_replica_user) + else + # on replica + local rplPasswordEscaped + rplPasswordEscaped=$(docker_sql_escape_string_literal "${MARIADB_REPLICATION_PASSWORD}") + # SC cannot follow how MARIADB_MASTER_PORT is assigned a default value. + # shellcheck disable=SC2153 + changeMasterTo="CHANGE MASTER TO MASTER_HOST='$MARIADB_MASTER_HOST', MASTER_USER='$MARIADB_REPLICATION_USER', MASTER_PASSWORD='$rplPasswordEscaped', MASTER_PORT=$MARIADB_MASTER_PORT, MASTER_CONNECT_RETRY=10;" + fi + fi + mysql_note "Securing system users (equivalent to running mysql_secure_installation)" # tell docker_process_sql to not use MARIADB_ROOT_PASSWORD since it is just now being set # --binary-mode to save us from the semi-mad users go out of their way to confuse the encoding. @@ -381,17 +493,77 @@ docker_setup_db() { ${rootCreate} ${mysqlAtLocalhost} ${mysqlAtLocalhostGrants} - -- pre-10.3 only - DROP DATABASE IF EXISTS test ; + ${createHealthCheckUsers} -- end of securing system users, rest of init now... SET @@SESSION.SQL_LOG_BIN=@orig_sql_log_bin; -- create users/databases ${createDatabase} ${createUser} + ${createReplicaUser} ${userGrants} + + ${changeMasterTo} EOSQL } +# create a new installation +docker_mariadb_init() +{ + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + if [ -n "$DATABASE_INIT_FROM_BACKUP" ]; then + shopt -s dotglob + for file in /docker-entrypoint-initdb.d/*.tar{.gz,.xz,.zst}; do + mkdir -p "$DATADIR"/.init + tar --auto-compress --extract --file "$file" --directory="$DATADIR"/.init + mariadb-backup --target-dir="$DATADIR"/.init --datadir="$DATADIR"/.restore --move-back + + mv "$DATADIR"/.restore/** "$DATADIR"/ + if [ -f "$DATADIR/.init/backup-my.cnf" ]; then + mv "$DATADIR/.init/backup-my.cnf" "$DATADIR/.my.cnf" + mysql_note "Adding startup configuration:" + my_print_defaults --defaults-file="$DATADIR/.my.cnf" --mariadbd + fi + rm -rf "$DATADIR"/.init "$DATADIR"/.restore + if [ "$(id -u)" = "0" ]; then + # this will cause less disk access than `chown -R` + find "$DATADIR" \! -user mysql \( -exec chown mysql: '{}' + -o -true \) + fi + done + if _check_if_upgrade_is_needed; then + docker_mariadb_upgrade "$@" + fi + return + fi + 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/* + # Wait until after /docker-entrypoint-initdb.d is performed before setting + # root@localhost password to a hash we don't know the password for. + if [ -n "${MARIADB_ROOT_PASSWORD_HASH}" ]; then + mysql_note "Setting root@localhost password hash" + docker_process_sql --dont-use-mysql-root-password --binary-mode <<-EOSQL + SET @@SESSION.SQL_LOG_BIN=0; + SET PASSWORD FOR 'root'@'localhost'= '${MARIADB_ROOT_PASSWORD_HASH}'; + EOSQL + fi + + mysql_note "Stopping temporary server" + docker_temp_server_stop + mysql_note "Temporary server stopped" + + echo + mysql_note "MariaDB init process done. Ready for start up." + echo +} + # backup the mysql database docker_mariadb_backup_system() { @@ -402,8 +574,8 @@ docker_mariadb_backup_system() fi local backup_db="system_mysql_backup_unknown_version.sql.zst" local oldfullversion="unknown_version" - if [ -r "$DATADIR"/mysql_upgrade_info ]; then - read -r -d '' oldfullversion < "$DATADIR"/mysql_upgrade_info || true + if [ -r "$DATADIR"/mariadb_upgrade_info ]; then + read -r -d '' oldfullversion < "$DATADIR"/mariadb_upgrade_info || true if [ -n "$oldfullversion" ]; then backup_db="system_mysql_backup_${oldfullversion}.sql.zst" fi @@ -421,17 +593,42 @@ docker_mariadb_backup_system() docker_mariadb_upgrade() { if [ -z "$MARIADB_AUTO_UPGRADE" ] \ || [ "$MARIADB_AUTO_UPGRADE" = 0 ]; then - mysql_note "MariaDB upgrade (mariadb-upgrade) required, but skipped due to \$MARIADB_AUTO_UPGRADE setting" + mysql_note "MariaDB upgrade (mariadb-upgrade or creating healthcheck users) required, but skipped due to \$MARIADB_AUTO_UPGRADE setting" return fi mysql_note "Starting temporary server" docker_temp_server_start "$@" --skip-grant-tables \ - --loose-innodb_buffer_pool_dump_at_shutdown=0 \ - --skip-slave-start + --loose-innodb_buffer_pool_dump_at_shutdown=0 mysql_note "Temporary server started." docker_mariadb_backup_system + if [ ! -f "$DATADIR"/.my-healthcheck.cnf ]; then + mysql_note "Creating healthcheck users" + local createHealthCheckUsers + createHealthCheckUsers=$(create_healthcheck_users) + docker_process_sql --dont-use-mysql-root-password --binary-mode <<-EOSQL + -- Healthcheck users shouldn't be replicated + SET @@SESSION.SQL_LOG_BIN=0; + -- we need the SQL_MODE NO_BACKSLASH_ESCAPES mode to be clear for the password to be set + SET @@SESSION.SQL_MODE=REPLACE(@@SESSION.SQL_MODE, 'NO_BACKSLASH_ESCAPES', ''); + FLUSH PRIVILEGES; + $createHealthCheckUsers +EOSQL + mysql_note "Stopping temporary server" + docker_temp_server_stop + mysql_note "Temporary server stopped" + + if _check_if_upgrade_is_needed; then + # need a restart as FLUSH PRIVILEGES isn't reversable + mysql_note "Restarting temporary server for upgrade" + docker_temp_server_start "$@" --skip-grant-tables \ + --loose-innodb_buffer_pool_dump_at_shutdown=0 + else + return 0 + fi + fi + mysql_note "Starting mariadb-upgrade" mariadb-upgrade --upgrade-system-tables mysql_note "Finished mariadb-upgrade" @@ -443,20 +640,24 @@ docker_mariadb_upgrade() { _check_if_upgrade_is_needed() { - if [ ! -f "$DATADIR"/mysql_upgrade_info ]; then + if [ ! -f "$DATADIR"/mariadb_upgrade_info ]; then mysql_note "MariaDB upgrade information missing, assuming required" return 0 fi local mariadbVersion mariadbVersion="$(_mariadb_version)" IFS='.-' read -ra newversion <<<"$mariadbVersion" - IFS='.-' read -ra oldversion < "$DATADIR"/mysql_upgrade_info || true + IFS='.-' read -ra oldversion < "$DATADIR"/mariadb_upgrade_info || true if [[ ${#newversion[@]} -lt 2 ]] || [[ ${#oldversion[@]} -lt 2 ]] \ || [[ ${oldversion[0]} -lt ${newversion[0]} ]] \ || [[ ${oldversion[0]} -eq ${newversion[0]} && ${oldversion[1]} -lt ${newversion[1]} ]]; then return 0 fi + if [ ! -f "$DATADIR"/.my-healthcheck.cnf ]; then + mysql_note "MariaDB heathcheck configation file missing, assuming desirable" + return 0 + fi mysql_note "MariaDB upgrade not required" return 1 } @@ -475,7 +676,7 @@ _mysql_want_help() { return 1 } -_main() { +_main_mariadb() { # if command starts with an option, prepend mariadbd if [ "${1:0:1}" = '-' ]; then set -- mariadbd "$@" @@ -501,34 +702,7 @@ _main() { if [ -z "$DATABASE_ALREADY_EXISTS" ]; then docker_verify_minimum_env - # check dir permissions to reduce likelihood of half-initialized database - ls /docker-entrypoint-initdb.d/ > /dev/null - - 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/* - # Wait until after /docker-entrypoint-initdb.d is performed before setting - # root@localhost password to a hash we don't know the password for. - if [ -n "${MARIADB_ROOT_PASSWORD_HASH}" ]; then - mysql_note "Setting root@localhost password hash" - docker_process_sql --dont-use-mysql-root-password --binary-mode <<-EOSQL - SET @@SESSION.SQL_LOG_BIN=0; - SET PASSWORD FOR 'root'@'localhost'= '${MARIADB_ROOT_PASSWORD_HASH}'; - EOSQL - fi - - mysql_note "Stopping temporary server" - docker_temp_server_stop - mysql_note "Temporary server stopped" - - echo - mysql_note "MariaDB init process done. Ready for start up." - echo + docker_mariadb_init "$@" # MDEV-27636 mariadb_upgrade --check-if-upgrade-is-needed cannot be run offline #elif mariadb-upgrade --check-if-upgrade-is-needed; then elif _check_if_upgrade_is_needed; then @@ -552,6 +726,10 @@ _run_web_server() { chown www-data:www-data /var/www/phpmyadmin/config.inc.php touch "/var/www/phpmyadmin/.installed" fi + + chown -R www-data:www-data /var/log/nginx + #touch /var/log/php8.3-fpm.log && chown www-data:www-data /var/log/php8.3-fpm.log + php-fpm8.3 & nginx & fi @@ -561,5 +739,6 @@ _run_web_server() { if ! _is_sourced; then _check_to_run_teleport _run_web_server - _main "$@" + + _main_mariadb "$@" fi