diff --git a/10.0/Dockerfile b/10.0/Dockerfile index 8a493aeb..843ba647 100644 --- a/10.0/Dockerfile +++ b/10.0/Dockerfile @@ -4,6 +4,8 @@ FROM debian:jessie # 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 + RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 199369E5404BD5FC7D2FE43BCBCB082A1BB943DB ENV MARIADB_MAJOR 10.0 @@ -18,6 +20,8 @@ RUN echo "deb http://ftp.osuosl.org/pub/mariadb/repo/$MARIADB_MAJOR/debian jessi # add repository pinning to make sure dependencies from this MariaDB repo are preferred over Debian dependencies # libmariadbclient18 : Depends: libmysqlclient18 (= 5.5.42+maria-1~wheezy) but 5.5.43-0+deb7u1 is to be installed +# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql) +# also, we set debconf keys to make APT a little quieter RUN { \ echo mariadb-server-$MARIADB_MAJOR mysql-server/root_password password 'unused'; \ echo mariadb-server-$MARIADB_MAJOR mysql-server/root_password_again password 'unused'; \ @@ -27,8 +31,13 @@ RUN { \ mariadb-server=$MARIADB_VERSION \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/mysql \ - && mkdir /var/lib/mysql \ - && sed -ri 's/^(bind-address|skip-networking)/;\1/' /etc/mysql/my.cnf + && mkdir /var/lib/mysql + +# comment out a few problematic configuration values +# don't reverse lookup hostnames, they are usually another container +RUN sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/my.cnf \ + && echo 'skip-host-cache\nskip-name-resolve' | awk '{ print } $1 == "[mysqld]" && c == 0 { c = 1; system("cat") }' /etc/mysql/my.cnf > /tmp/my.cnf \ + && mv /tmp/my.cnf /etc/mysql/my.cnf VOLUME /var/lib/mysql diff --git a/10.0/docker-entrypoint.sh b/10.0/docker-entrypoint.sh index 46f60d12..b32549b4 100755 --- a/10.0/docker-entrypoint.sh +++ b/10.0/docker-entrypoint.sh @@ -1,54 +1,97 @@ #!/bin/bash set -e +# if command starts with an option, prepend mysqld if [ "${1:0:1}" = '-' ]; then set -- mysqld "$@" fi if [ "$1" = 'mysqld' ]; then - # read DATADIR from the MySQL config + # Get config DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" - + if [ ! -d "$DATADIR/mysql" ]; then if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then echo >&2 'error: database is uninitialized and MYSQL_ROOT_PASSWORD not set' echo >&2 ' Did you forget to add -e MYSQL_ROOT_PASSWORD=... ?' exit 1 fi - - echo 'Running mysql_install_db ...' - mysql_install_db --datadir="$DATADIR" + + mkdir -p "$DATADIR" + chown -R mysql:mysql "$DATADIR" + + echo 'Running mysql_install_db' + mysql_install_db --user=mysql --datadir="$DATADIR" --rpm echo 'Finished mysql_install_db' - - # 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='/tmp/mysql-first-time.sql' - cat > "$tempSqlFile" <<-EOSQL + + mysqld --user=mysql --datadir="$DATADIR" --skip-networking & + 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 + 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[@]}" mysql + + "${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 ; 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 + + echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" fi - - echo 'FLUSH PRIVILEGES ;' >> "$tempSqlFile" - - set -- "$@" --init-file="$tempSqlFile" + + 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 ! 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" fi diff --git a/5.5/Dockerfile b/5.5/Dockerfile index 587dccaa..f671728a 100644 --- a/5.5/Dockerfile +++ b/5.5/Dockerfile @@ -4,6 +4,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 + RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 199369E5404BD5FC7D2FE43BCBCB082A1BB943DB ENV MARIADB_MAJOR 5.5 @@ -18,6 +20,8 @@ RUN echo "deb http://ftp.osuosl.org/pub/mariadb/repo/$MARIADB_MAJOR/debian wheez # add repository pinning to make sure dependencies from this MariaDB repo are preferred over Debian dependencies # libmariadbclient18 : Depends: libmysqlclient18 (= 5.5.42+maria-1~wheezy) but 5.5.43-0+deb7u1 is to be installed +# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql) +# also, we set debconf keys to make APT a little quieter RUN { \ echo mariadb-server-$MARIADB_MAJOR mysql-server/root_password password 'unused'; \ echo mariadb-server-$MARIADB_MAJOR mysql-server/root_password_again password 'unused'; \ @@ -27,8 +31,13 @@ RUN { \ mariadb-server=$MARIADB_VERSION \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/mysql \ - && mkdir /var/lib/mysql \ - && sed -ri 's/^(bind-address|skip-networking)/;\1/' /etc/mysql/my.cnf + && mkdir /var/lib/mysql + +# comment out a few problematic configuration values +# don't reverse lookup hostnames, they are usually another container +RUN sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/my.cnf \ + && echo 'skip-host-cache\nskip-name-resolve' | awk '{ print } $1 == "[mysqld]" && c == 0 { c = 1; system("cat") }' /etc/mysql/my.cnf > /tmp/my.cnf \ + && mv /tmp/my.cnf /etc/mysql/my.cnf VOLUME /var/lib/mysql diff --git a/5.5/docker-entrypoint.sh b/5.5/docker-entrypoint.sh index 46f60d12..b32549b4 100755 --- a/5.5/docker-entrypoint.sh +++ b/5.5/docker-entrypoint.sh @@ -1,54 +1,97 @@ #!/bin/bash set -e +# if command starts with an option, prepend mysqld if [ "${1:0:1}" = '-' ]; then set -- mysqld "$@" fi if [ "$1" = 'mysqld' ]; then - # read DATADIR from the MySQL config + # Get config DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" - + if [ ! -d "$DATADIR/mysql" ]; then if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then echo >&2 'error: database is uninitialized and MYSQL_ROOT_PASSWORD not set' echo >&2 ' Did you forget to add -e MYSQL_ROOT_PASSWORD=... ?' exit 1 fi - - echo 'Running mysql_install_db ...' - mysql_install_db --datadir="$DATADIR" + + mkdir -p "$DATADIR" + chown -R mysql:mysql "$DATADIR" + + echo 'Running mysql_install_db' + mysql_install_db --user=mysql --datadir="$DATADIR" --rpm echo 'Finished mysql_install_db' - - # 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='/tmp/mysql-first-time.sql' - cat > "$tempSqlFile" <<-EOSQL + + mysqld --user=mysql --datadir="$DATADIR" --skip-networking & + 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 + 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[@]}" mysql + + "${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 ; 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 + + echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" fi - - echo 'FLUSH PRIVILEGES ;' >> "$tempSqlFile" - - set -- "$@" --init-file="$tempSqlFile" + + 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 ! 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" fi diff --git a/Dockerfile.template b/Dockerfile.template index 82d55cff..6c0f977f 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -4,6 +4,8 @@ FROM debian:%%SUITE%% # 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 + RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys 199369E5404BD5FC7D2FE43BCBCB082A1BB943DB ENV MARIADB_MAJOR %%MARIADB_MAJOR%% @@ -18,6 +20,8 @@ RUN echo "deb http://ftp.osuosl.org/pub/mariadb/repo/$MARIADB_MAJOR/debian %%SUI # add repository pinning to make sure dependencies from this MariaDB repo are preferred over Debian dependencies # libmariadbclient18 : Depends: libmysqlclient18 (= 5.5.42+maria-1~wheezy) but 5.5.43-0+deb7u1 is to be installed +# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn't have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql) +# also, we set debconf keys to make APT a little quieter RUN { \ echo mariadb-server-$MARIADB_MAJOR mysql-server/root_password password 'unused'; \ echo mariadb-server-$MARIADB_MAJOR mysql-server/root_password_again password 'unused'; \ @@ -27,8 +31,13 @@ RUN { \ mariadb-server=$MARIADB_VERSION \ && rm -rf /var/lib/apt/lists/* \ && rm -rf /var/lib/mysql \ - && mkdir /var/lib/mysql \ - && sed -ri 's/^(bind-address|skip-networking)/;\1/' /etc/mysql/my.cnf + && mkdir /var/lib/mysql + +# comment out a few problematic configuration values +# don't reverse lookup hostnames, they are usually another container +RUN sed -Ei 's/^(bind-address|log)/#&/' /etc/mysql/my.cnf \ + && echo 'skip-host-cache\nskip-name-resolve' | awk '{ print } $1 == "[mysqld]" && c == 0 { c = 1; system("cat") }' /etc/mysql/my.cnf > /tmp/my.cnf \ + && mv /tmp/my.cnf /etc/mysql/my.cnf VOLUME /var/lib/mysql diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 46f60d12..b32549b4 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,54 +1,97 @@ #!/bin/bash set -e +# if command starts with an option, prepend mysqld if [ "${1:0:1}" = '-' ]; then set -- mysqld "$@" fi if [ "$1" = 'mysqld' ]; then - # read DATADIR from the MySQL config + # Get config DATADIR="$("$@" --verbose --help 2>/dev/null | awk '$1 == "datadir" { print $2; exit }')" - + if [ ! -d "$DATADIR/mysql" ]; then if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" ]; then echo >&2 'error: database is uninitialized and MYSQL_ROOT_PASSWORD not set' echo >&2 ' Did you forget to add -e MYSQL_ROOT_PASSWORD=... ?' exit 1 fi - - echo 'Running mysql_install_db ...' - mysql_install_db --datadir="$DATADIR" + + mkdir -p "$DATADIR" + chown -R mysql:mysql "$DATADIR" + + echo 'Running mysql_install_db' + mysql_install_db --user=mysql --datadir="$DATADIR" --rpm echo 'Finished mysql_install_db' - - # 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='/tmp/mysql-first-time.sql' - cat > "$tempSqlFile" <<-EOSQL + + mysqld --user=mysql --datadir="$DATADIR" --skip-networking & + 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 + 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[@]}" mysql + + "${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 ; 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 + + echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" fi - - echo 'FLUSH PRIVILEGES ;' >> "$tempSqlFile" - - set -- "$@" --init-file="$tempSqlFile" + + 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 ! 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" fi