From 14f165596ea8808dfeb2131f092aabe61c967225 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Tue, 4 Aug 2015 15:57:59 -0700 Subject: [PATCH] Add support for "/docker-entrypoint-initdb.d" similar to PostgreSQL's implementation This also cleans up some minor unnecessary bits in `docker-entrypoint.sh` so that it's more consistent. Compare to https://github.com/docker-library/postgres/blob/a82c28e1c407ef5ddfc2a6014dac87bcc4955a26/docker-entrypoint.sh#L49-L97 --- 5.5/Dockerfile | 3 ++ 5.5/docker-entrypoint.sh | 74 ++++++++++++++++++---------------------- 5.6/Dockerfile | 2 ++ 5.6/docker-entrypoint.sh | 71 ++++++++++++++++++-------------------- 5.7/Dockerfile | 2 ++ 5.7/docker-entrypoint.sh | 71 ++++++++++++++++++-------------------- 6 files changed, 107 insertions(+), 116 deletions(-) diff --git a/5.5/Dockerfile b/5.5/Dockerfile index 4ae75f8a4..af9e7ea43 100644 --- a/5.5/Dockerfile +++ b/5.5/Dockerfile @@ -1,7 +1,10 @@ FROM debian:wheezy + # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added RUN groupadd -r mysql && useradd -r -g mysql mysql +RUN mkdir /docker-entrypoint-initdb.d + # FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db: # File::Basename # File::Copy diff --git a/5.5/docker-entrypoint.sh b/5.5/docker-entrypoint.sh index e0cdba8c6..34dc9e346 100755 --- a/5.5/docker-entrypoint.sh +++ b/5.5/docker-entrypoint.sh @@ -1,17 +1,6 @@ #!/bin/bash set -e -get_option () { - local section=$1 - local option=$2 - local default=$3 - # my_print_defaults can output duplicates, if an option exists both globally and in - # a custom config file. We pick the last occurence, which is from the custom config. - ret=$(my_print_defaults $section | grep '^--'${option}'=' | cut -d= -f2- | tail -n1) - [ -z $ret ] && ret=$default - echo $ret -} - # if command starts with an option, prepend mysqld if [ "${1:0:1}" = '-' ]; then set -- mysqld "$@" @@ -20,9 +9,6 @@ fi if [ "$1" = 'mysqld' ]; then # Get config DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" - SOCKET=$(get_option mysqld socket "/tmp/mysql.sock") - HOSTNAME=$(hostname) - PIDFILE=$(get_option mysqld pid-file "$DATADIR/mysqld.pid") if [ ! -d "$DATADIR/mysql" ]; then if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then @@ -38,25 +24,26 @@ if [ "$1" = 'mysqld' ]; then mysql_install_db --user=mysql --datadir="$DATADIR" --rpm --basedir=/usr/local/mysql echo 'Finished mysql_install_db' - mysqld --user=mysql --datadir="$DATADIR" --skip-networking --basedir=/usr/local/mysql --pid-file="$PIDFILE" & - for i in $(seq 30 -1 0); do - [ -S "$SOCKET" ] && break + mysqld --user=mysql --datadir="$DATADIR" --skip-networking --basedir=/usr/local/mysql & + pid="$!" + + mysql=( mysql --protocol=socket -uroot ) + + for i in {30..0}; do + if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then + break + fi echo 'MySQL init process in progress...' sleep 1 done - if [ $i = 0 ]; then + if [ "$i" = 0 ]; then echo >&2 'MySQL init process failed.' exit 1 fi - mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql --protocol=socket -uroot mysql + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql - # These statements _must_ be on individual lines, and _must_ end with - # semicolons (no line breaks or comments are permitted). - # TODO proper SQL escaping on ALL the things D: - - tempSqlFile=$(mktemp /tmp/mysql-first-time.XXXXXX.sql) - cat > "$tempSqlFile" <<-EOSQL + "${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; @@ -65,36 +52,43 @@ if [ "$1" = 'mysqld' ]; then CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ; DROP DATABASE IF EXISTS test ; + FLUSH PRIVILEGES ; EOSQL + mysql+=( -p"${MYSQL_ROOT_PASSWORD}" ) if [ "$MYSQL_DATABASE" ]; then - echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" >> "$tempSqlFile" + echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" + mysql+=( "$MYSQL_DATABASE" ) fi if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then - echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" >> "$tempSqlFile" + echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" | "${mysql[@]}" if [ "$MYSQL_DATABASE" ]; then - echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" >> "$tempSqlFile" + echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" | "${mysql[@]}" fi - fi - - echo 'FLUSH PRIVILEGES ;' >> "$tempSqlFile" - mysql --protocol=socket -uroot < "$tempSqlFile" + echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" + fi - rm -f "$tempSqlFile" - kill $(cat $PIDFILE) - for i in $(seq 30 -1 0); do - [ -f "$PIDFILE" ] || break - echo 'MySQL init process in progress...' - sleep 1 + 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 ;; + *) echo "$0: ignoring $f" ;; + esac + echo done - if [ $i = 0 ]; then - echo >&2 'MySQL hangs during init process.' + + if ! kill -s TERM "$pid" || ! wait "$pid"; then + echo >&2 'MySQL init process failed.' exit 1 fi + + echo echo 'MySQL init process done. Ready for start up.' + echo fi chown -R mysql:mysql "$DATADIR" diff --git a/5.6/Dockerfile b/5.6/Dockerfile index 766a48b73..c18e7ac6b 100644 --- a/5.6/Dockerfile +++ b/5.6/Dockerfile @@ -3,6 +3,8 @@ FROM debian:wheezy # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added RUN groupadd -r mysql && useradd -r -g mysql mysql +RUN mkdir /docker-entrypoint-initdb.d + # FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db: # File::Basename # File::Copy diff --git a/5.6/docker-entrypoint.sh b/5.6/docker-entrypoint.sh index 6f011f660..227cc7f2f 100755 --- a/5.6/docker-entrypoint.sh +++ b/5.6/docker-entrypoint.sh @@ -1,17 +1,6 @@ #!/bin/bash set -e -get_option () { - local section=$1 - local option=$2 - local default=$3 - # my_print_defaults can output duplicates, if an option exists both globally and in - # a custom config file. We pick the last occurence, which is from the custom config. - ret=$(my_print_defaults $section | grep '^--'${option}'=' | cut -d= -f2- | tail -n1) - [ -z $ret ] && ret=$default - echo $ret -} - # if command starts with an option, prepend mysqld if [ "${1:0:1}" = '-' ]; then set -- mysqld "$@" @@ -20,8 +9,6 @@ fi if [ "$1" = 'mysqld' ]; then # Get config DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" - SOCKET=$(get_option mysqld socket "$DATADIR/mysql.sock") - PIDFILE=$(get_option mysqld pid-file "/var/run/mysqld/mysqld.pid") if [ ! -d "$DATADIR/mysql" ]; then if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then @@ -38,25 +25,26 @@ if [ "$1" = 'mysqld' ]; then echo 'Finished mysql_install_db' mysqld --user=mysql --datadir="$DATADIR" --skip-networking & - for i in $(seq 30 -1 0); do - [ -S "$SOCKET" ] && break + pid="$!" + + mysql=( mysql --protocol=socket -uroot ) + + for i in {30..0}; do + if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then + break + fi echo 'MySQL init process in progress...' sleep 1 done - if [ $i = 0 ]; then + if [ "$i" = 0 ]; then echo >&2 'MySQL init process failed.' exit 1 fi # 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 --protocol=socket -uroot mysql + mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql - # These statements _must_ be on individual lines, and _must_ end with - # semicolons (no line breaks or comments are permitted). - # TODO proper SQL escaping on ALL the things D: - - tempSqlFile=$(mktemp /tmp/mysql-first-time.XXXXXX.sql) - cat > "$tempSqlFile" <<-EOSQL + "${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; @@ -65,36 +53,43 @@ if [ "$1" = 'mysqld' ]; then CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ; DROP DATABASE IF EXISTS test ; + FLUSH PRIVILEGES ; EOSQL + mysql+=( -p"${MYSQL_ROOT_PASSWORD}" ) if [ "$MYSQL_DATABASE" ]; then - echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" >> "$tempSqlFile" + echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" + mysql+=( "$MYSQL_DATABASE" ) fi if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then - echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" >> "$tempSqlFile" + echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" | "${mysql[@]}" if [ "$MYSQL_DATABASE" ]; then - echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" >> "$tempSqlFile" + echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" | "${mysql[@]}" fi - fi - - echo 'FLUSH PRIVILEGES ;' >> "$tempSqlFile" - mysql --protocol=socket -uroot < "$tempSqlFile" + echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" + fi - rm -f "$tempSqlFile" - kill $(cat $PIDFILE) - for i in $(seq 30 -1 0); do - [ -f "$PIDFILE" ] || break - echo 'MySQL init process in progress...' - sleep 1 + 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 ;; + *) echo "$0: ignoring $f" ;; + esac + echo done - if [ $i = 0 ]; then - echo >&2 'MySQL hangs during init process.' + + if ! kill -s TERM "$pid" || ! wait "$pid"; then + echo >&2 'MySQL init process failed.' exit 1 fi + + echo echo 'MySQL init process done. Ready for start up.' + echo fi chown -R mysql:mysql "$DATADIR" diff --git a/5.7/Dockerfile b/5.7/Dockerfile index 6dab707d4..7d637851a 100644 --- a/5.7/Dockerfile +++ b/5.7/Dockerfile @@ -3,6 +3,8 @@ FROM debian:wheezy # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added RUN groupadd -r mysql && useradd -r -g mysql mysql +RUN mkdir /docker-entrypoint-initdb.d + # FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db: # File::Basename # File::Copy diff --git a/5.7/docker-entrypoint.sh b/5.7/docker-entrypoint.sh index 69d451940..8cd2cc4ca 100755 --- a/5.7/docker-entrypoint.sh +++ b/5.7/docker-entrypoint.sh @@ -1,17 +1,6 @@ #!/bin/bash set -e -get_option () { - local section=$1 - local option=$2 - local default=$3 - # my_print_defaults can output duplicates, if an option exists both globally and in - # a custom config file. We pick the last occurence, which is from the custom config. - ret=$(my_print_defaults $section | grep '^--'${option}'=' | cut -d= -f2- | tail -n1) - [ -z $ret ] && ret=$default - echo $ret -} - # if command starts with an option, prepend mysqld if [ "${1:0:1}" = '-' ]; then set -- mysqld "$@" @@ -20,8 +9,6 @@ fi if [ "$1" = 'mysqld' ]; then # Get config DATADIR="$("$@" --verbose --help --innodb-read-only 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" - SOCKET=$(get_option mysqld socket "$DATADIR/mysql.sock") - PIDFILE=$(get_option mysqld pid-file "/var/run/mysqld/mysqld.pid") if [ ! -d "$DATADIR/mysql" ]; then if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then @@ -38,24 +25,25 @@ if [ "$1" = 'mysqld' ]; then echo 'Database initialized' mysqld --user=mysql --datadir="$DATADIR" --skip-networking & - for i in $(seq 30 -1 0); do - [ -S $SOCKET ] && break + pid="$!" + + mysql=( mysql --protocol=socket -uroot ) + + for i in {30..0}; do + if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then + break + fi echo 'MySQL init process in progress...' sleep 1 done - if [ $i = 0 ]; then + if [ "$i" = 0 ]; then echo >&2 'MySQL init process failed.' exit 1 fi - mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql --protocol=socket -uroot mysql + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql - # These statements _must_ be on individual lines, and _must_ end with - # semicolons (no line breaks or comments are permitted). - # TODO proper SQL escaping on ALL the things D: - - tempSqlFile=$(mktemp /tmp/mysql-first-time.XXXXXX.sql) - cat > "$tempSqlFile" <<-EOSQL + "${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; @@ -64,36 +52,43 @@ if [ "$1" = 'mysqld' ]; then CREATE USER 'root'@'%' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; GRANT ALL ON *.* TO 'root'@'%' WITH GRANT OPTION ; DROP DATABASE IF EXISTS test ; + FLUSH PRIVILEGES ; EOSQL + mysql+=( -p"${MYSQL_ROOT_PASSWORD}" ) if [ "$MYSQL_DATABASE" ]; then - echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" >> "$tempSqlFile" + echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}" + mysql+=( "$MYSQL_DATABASE" ) fi if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then - echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" >> "$tempSqlFile" + echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" | "${mysql[@]}" if [ "$MYSQL_DATABASE" ]; then - echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" >> "$tempSqlFile" + echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" | "${mysql[@]}" fi - fi - - echo 'FLUSH PRIVILEGES ;' >> "$tempSqlFile" - mysql --protocol=socket -uroot < "$tempSqlFile" + echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" + fi - rm -f "$tempSqlFile" - kill $(cat $PIDFILE) - for i in $(seq 30 -1 0); do - [ -f "$PIDFILE" ] || break - echo 'MySQL init process in progress...' - sleep 1 + 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 ;; + *) echo "$0: ignoring $f" ;; + esac + echo done - if [ $i = 0 ]; then - echo >&2 'MySQL hangs during init process.' + + if ! kill -s TERM "$pid" || ! wait "$pid"; then + echo >&2 'MySQL init process failed.' exit 1 fi + + echo echo 'MySQL init process done. Ready for start up.' + echo fi chown -R mysql:mysql "$DATADIR"