diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..e43b0f988 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 81431783b..000000000 --- a/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -language: bash - -# for secret experimental features ;) -sudo: 9000 - -env: - - VERSION=5.7 - - VERSION=5.6 - - VERSION=5.5 - -install: - - git clone https://github.com/docker-library/official-images.git ~/official-images - -before_script: - - env | sort - - cd "$VERSION" - - image="mysql:$VERSION" - -script: - - docker build -t "$image" . - - ~/official-images/test/run.sh "$image" - -after_script: - - docker images - -# vim:set et ts=2 sw=2: diff --git a/5.5/Dockerfile b/5.5/Dockerfile deleted file mode 100644 index 90d840332..000000000 --- a/5.5/Dockerfile +++ /dev/null @@ -1,59 +0,0 @@ -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 -# Sys::Hostname -# Data::Dumper -RUN apt-get update && apt-get install -y perl --no-install-recommends && rm -rf /var/lib/apt/lists/* - -# mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory -RUN apt-get update && apt-get install -y libaio1 && rm -rf /var/lib/apt/lists/* - -# gpg: key 5072E1F5: public key "MySQL Release Engineering " imported -RUN gpg --keyserver ha.pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 - -ENV MYSQL_MAJOR 5.5 -ENV MYSQL_VERSION 5.5.45 - -# note: we're pulling the *.asc file from mysql.he.net instead of dev.mysql.com because the official mirror 404s that file for whatever reason - maybe it's at a different path? -RUN apt-get update && apt-get install -y curl --no-install-recommends && rm -rf /var/lib/apt/lists/* \ - && curl -SL "http://dev.mysql.com/get/Downloads/MySQL-$MYSQL_MAJOR/mysql-$MYSQL_VERSION-linux2.6-x86_64.tar.gz" -o mysql.tar.gz \ - && curl -SL "http://mysql.he.net/Downloads/MySQL-$MYSQL_MAJOR/mysql-$MYSQL_VERSION-linux2.6-x86_64.tar.gz.asc" -o mysql.tar.gz.asc \ - && apt-get purge -y --auto-remove curl \ - && gpg --verify mysql.tar.gz.asc \ - && mkdir /usr/local/mysql \ - && tar -xzf mysql.tar.gz -C /usr/local/mysql --strip-components=1 \ - && rm mysql.tar.gz* \ - && rm -rf /usr/local/mysql/mysql-test /usr/local/mysql/sql-bench \ - && rm -rf /usr/local/mysql/bin/*-debug /usr/local/mysql/bin/*_embedded \ - && find /usr/local/mysql -type f -name "*.a" -delete \ - && apt-get update && apt-get install -y binutils && rm -rf /var/lib/apt/lists/* \ - && { find /usr/local/mysql -type f -executable -exec strip --strip-all '{}' + || true; } \ - && apt-get purge -y --auto-remove binutils -ENV PATH $PATH:/usr/local/mysql/bin:/usr/local/mysql/scripts - -# replicate some of the way the APT package configuration works -# this is only for 5.5 since it doesn't have an APT repo, and will go away when 5.5 does -RUN mkdir -p /etc/mysql/conf.d \ - && { \ - echo '[mysqld]'; \ - echo 'skip-host-cache'; \ - echo 'skip-name-resolve'; \ - echo 'user = mysql'; \ - echo 'datadir = /var/lib/mysql'; \ - echo '!includedir /etc/mysql/conf.d/'; \ - } > /etc/mysql/my.cnf - -VOLUME /var/lib/mysql - -COPY docker-entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] - -EXPOSE 3306 -CMD ["mysqld"] diff --git a/5.5/docker-entrypoint.sh b/5.5/docker-entrypoint.sh deleted file mode 100755 index 34dc9e346..000000000 --- a/5.5/docker-entrypoint.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/bash -set -e - -# if command starts with an option, prepend mysqld -if [ "${1:0:1}" = '-' ]; then - set -- mysqld "$@" -fi - -if [ "$1" = 'mysqld' ]; then - # 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 - - mkdir -p "$DATADIR" - chown -R mysql:mysql "$DATADIR" - - echo 'Running mysql_install_db' - 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="$!" - - 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 - - mysql_tzinfo_to_sql /usr/share/zoneinfo | "${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\` ;" | "${mysql[@]}" - mysql+=( "$MYSQL_DATABASE" ) - fi - - if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then - echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" | "${mysql[@]}" - - if [ "$MYSQL_DATABASE" ]; then - echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" | "${mysql[@]}" - fi - - echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" - 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 ;; - *) 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 - -exec "$@" diff --git a/5.6/Dockerfile b/5.6/Dockerfile deleted file mode 100644 index 3487a8035..000000000 --- a/5.6/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -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 -# Sys::Hostname -# Data::Dumper -RUN apt-get update && apt-get install -y perl --no-install-recommends && rm -rf /var/lib/apt/lists/* - -# gpg: key 5072E1F5: public key "MySQL Release Engineering " imported -RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 - -ENV MYSQL_MAJOR 5.6 -ENV MYSQL_VERSION 5.6.26 - -RUN echo "deb http://repo.mysql.com/apt/debian/ wheezy mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list - -# 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 mysql-community-server mysql-community-server/data-dir select ''; \ - echo mysql-community-server mysql-community-server/root-pass password ''; \ - echo mysql-community-server mysql-community-server/re-root-pass password ''; \ - echo mysql-community-server mysql-community-server/remove-test-db select false; \ - } | debconf-set-selections \ - && apt-get update && apt-get install -y mysql-server="${MYSQL_VERSION}"* && rm -rf /var/lib/apt/lists/* \ - && rm -rf /var/lib/mysql && mkdir -p /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 - -COPY docker-entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] - -EXPOSE 3306 -CMD ["mysqld"] diff --git a/5.6/docker-entrypoint.sh b/5.6/docker-entrypoint.sh deleted file mode 100755 index 227cc7f2f..000000000 --- a/5.6/docker-entrypoint.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash -set -e - -# if command starts with an option, prepend mysqld -if [ "${1:0:1}" = '-' ]; then - set -- mysqld "$@" -fi - -if [ "$1" = 'mysqld' ]; then - # 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 - - mkdir -p "$DATADIR" - chown -R mysql:mysql "$DATADIR" - - echo 'Running mysql_install_db' - mysql_install_db --user=mysql --datadir="$DATADIR" --rpm --keep-my-cnf - echo 'Finished mysql_install_db' - - 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\` ;" | "${mysql[@]}" - mysql+=( "$MYSQL_DATABASE" ) - fi - - if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then - echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" | "${mysql[@]}" - - if [ "$MYSQL_DATABASE" ]; then - echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" | "${mysql[@]}" - fi - - echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" - 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 ;; - *) 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 - -exec "$@" diff --git a/5.7/Dockerfile b/5.7/Dockerfile deleted file mode 100644 index d6316b5b4..000000000 --- a/5.7/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -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 -# Sys::Hostname -# Data::Dumper -RUN apt-get update && apt-get install -y perl --no-install-recommends && rm -rf /var/lib/apt/lists/* - -# gpg: key 5072E1F5: public key "MySQL Release Engineering " imported -RUN apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys A4A9406876FCBD3C456770C88C718D3B5072E1F5 - -ENV MYSQL_MAJOR 5.7 -ENV MYSQL_VERSION 5.7.8-rc - -RUN echo "deb http://repo.mysql.com/apt/debian/ wheezy mysql-${MYSQL_MAJOR}-dmr" > /etc/apt/sources.list.d/mysql.list - -# 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 mysql-community-server mysql-community-server/data-dir select ''; \ - echo mysql-community-server mysql-community-server/root-pass password ''; \ - echo mysql-community-server mysql-community-server/re-root-pass password ''; \ - echo mysql-community-server mysql-community-server/remove-test-db select false; \ - } | debconf-set-selections \ - && apt-get update && apt-get install -y mysql-server="${MYSQL_VERSION}"* && rm -rf /var/lib/apt/lists/* \ - && rm -rf /var/lib/mysql && mkdir -p /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 - -COPY docker-entrypoint.sh /entrypoint.sh -ENTRYPOINT ["/entrypoint.sh"] - -EXPOSE 3306 -CMD ["mysqld"] diff --git a/5.7/docker-entrypoint.sh b/5.7/docker-entrypoint.sh deleted file mode 100755 index 8cd2cc4ca..000000000 --- a/5.7/docker-entrypoint.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/bash -set -e - -# if command starts with an option, prepend mysqld -if [ "${1:0:1}" = '-' ]; then - set -- mysqld "$@" -fi - -if [ "$1" = 'mysqld' ]; then - # Get config - DATADIR="$("$@" --verbose --help --innodb-read-only 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 - - mkdir -p "$DATADIR" - chown -R mysql:mysql "$DATADIR" - - echo 'Initializing database' - mysqld --initialize-insecure=on --datadir="$DATADIR" - echo 'Database initialized' - - 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 - - mysql_tzinfo_to_sql /usr/share/zoneinfo | "${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\` ;" | "${mysql[@]}" - mysql+=( "$MYSQL_DATABASE" ) - fi - - if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then - echo "CREATE USER '"$MYSQL_USER"'@'%' IDENTIFIED BY '"$MYSQL_PASSWORD"' ;" | "${mysql[@]}" - - if [ "$MYSQL_DATABASE" ]; then - echo "GRANT ALL ON \`"$MYSQL_DATABASE"\`.* TO '"$MYSQL_USER"'@'%' ;" | "${mysql[@]}" - fi - - echo 'FLUSH PRIVILEGES ;' | "${mysql[@]}" - 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 ;; - *) 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 - -exec "$@" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..c561cd9f6 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,18 @@ +We welcome your code contributions. Before submitting code via a GitHub pull +request, or by filing a bug in https://bugs.mysql.com you will need to have +signed the Oracle Contributor Agreement (see https://oca.opensource.oracle.com). + +Only pull requests from committers that can be verified as having signed the OCA +can be accepted. + +Submitting a contribution +-------------------------- + +1. Make sure you have a user account at bugs.mysql.com. You'll need to reference this + user account when you submit your OCA (Oracle Contributor Agreement). +2. Sign the Oracle OCA. You can find instructions for doing that at the OCA Page, + at https://oca.opensource.oracle.com +3. Validate your contribution by including tests that sufficiently cover the functionality. +4. Verify that the entire test suite passes with your code applied. +5. Submit your pull request via GitHub or uploading it using the contribution tab to a bug + record in https://bugs.mysql.com (using the 'contribution' tab). diff --git a/LICENSE b/LICENSE deleted file mode 100644 index d159169d1..000000000 --- a/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/README.md b/README.md index 4bc4ea1bd..93e29dd22 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,5 @@ -# About this Repo +# About This Repository -This is the Git repo of the official Docker image for [mysql](https://registry.hub.docker.com/_/mysql/). See the -Hub page for the full readme on how to use the Docker image and for information -regarding contributing and issues. +This repository collects files and tools related to creating Container (Docker) images for different MySQL products. -The full readme is generated over in [docker-library/docs](https://github.com/docker-library/docs), -specificially in [docker-library/docs/mysql](https://github.com/docker-library/docs/tree/master/mysql). +Please refer to the indvidual directories for information, including licenses, for the individual products. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..e43f9fb4c --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,30 @@ +Reporting security vulnerabilities +==================== +Oracle values the independent security research community and believes that +responsible disclosure of security vulnerabilities helps us ensure the security +and privacy of all our users. + +Please do NOT raise a GitHub Issue to report a security vulnerability. If you +believe you have found a security vulnerability, please submit a report to +secalert_us@oracle.com preferably with a proof of concept. Please review +some additional information on how to report security vulnerabilities to Oracle +(see https://www.oracle.com/corporate/security-practices/assurance/vulnerability/reporting.html) +We encourage people who contact Oracle Security to use email encryption using +our encryption key (see https://www.oracle.com/security-alerts/encryptionkey.html) + +We ask that you do not use other channels or contact the project maintainers +directly. + +Security updates, alerts and bulletins +------------------------------------- +Security updates will be released on a regular cadence. Many of our projects +will typically release security fixes in conjunction with the Oracle Critical Patch +Update program. Additional information, including past advisories, is available on our +security alerts page at https://www.oracle.com/security-alerts/ + +Security-related information +---------------------------- +We will provide security related information such as a threat model, considerations +for secure use, or any known security issues in our documentation. Please note +that labs and sample code are intended to demonstrate a concept and may not be +sufficiently hardened for production use. diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh deleted file mode 100755 index 25be45d95..000000000 --- a/generate-stackbrew-library.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -set -e - -declare -A aliases -aliases=( - [5.6]='5 latest' -) - -cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" - -versions=( */ ) -versions=( "${versions[@]%/}" ) -url='git://github.com/docker-library/mysql' - -echo '# maintainer: InfoSiftr (@infosiftr)' - -for version in "${versions[@]}"; do - commit="$(cd "$version" && git log -1 --format='format:%H' -- Dockerfile $(awk 'toupper($1) == "COPY" { for (i = 2; i < NF; i++) { print $i } }' Dockerfile))" - fullVersion="$(grep -m1 'ENV MYSQL_VERSION ' "$version/Dockerfile" | cut -d' ' -f3)" - versionAliases=() - while [ "$fullVersion" != "$version" -a "${fullVersion%[.-]*}" != "$fullVersion" ]; do - versionAliases+=( $fullVersion ) - fullVersion="${fullVersion%[.-]*}" - done - versionAliases+=( $version ${aliases[$version]} ) - - echo - for va in "${versionAliases[@]}"; do - echo "$va: ${url}@${commit} $version" - done -done diff --git a/mysql-cluster/7.5/Dockerfile b/mysql-cluster/7.5/Dockerfile new file mode 100644 index 000000000..be07c11ae --- /dev/null +++ b/mysql-cluster/7.5/Dockerfile @@ -0,0 +1,45 @@ +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +FROM container-registry.oracle.com/os/oraclelinux:7-slim + +ARG MYSQL_SERVER_PACKAGE=mysql-cluster-community-server-minimal-7.5.32 +ARG MYSQL_SHELL_PACKAGE=mysql-shell-8.0.35 + +# Setup repositories for minimal packages (all versions) +RUN rpm -U http://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/mysql-cluster-community-minimal-release-el7.rpm \ + && rpm -U http://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/mysql80-community-release-el7.rpm + +# Install server and shell 8.0 +RUN yum install -y $MYSQL_SHELL_PACKAGE \ + && yum install -y $MYSQL_SERVER_PACKAGE --enablerepo=mysql-cluster75-community-minimal\ + && yum clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/7.5/cnf/my.cnf b/mysql-cluster/7.5/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/7.5/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/7.5/cnf/mysql-cluster.cnf b/mysql-cluster/7.5/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/7.5/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/7.5/docker-entrypoint.sh b/mysql-cluster/7.5/docker-entrypoint.sh new file mode 100755 index 000000000..5b53d0a89 --- /dev/null +++ b/mysql-cluster/7.5/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 7.5.32-1.2.14-cluster" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --verbose --help 2>&1 > /dev/null) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" </dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --verbose --help 2>&1 > /dev/null) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-cluster80-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/8.0/cnf/my.cnf b/mysql-cluster/8.0/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/8.0/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/8.0/cnf/mysql-cluster.cnf b/mysql-cluster/8.0/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/8.0/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/8.0/docker-entrypoint.sh b/mysql-cluster/8.0/docker-entrypoint.sh new file mode 100755 index 000000000..5db15e90f --- /dev/null +++ b/mysql-cluster/8.0/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 8.0.44-1.2.23-cluster" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol8_appstream \ + --enablerepo=mysql-cluster-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/8.1/cnf/my.cnf b/mysql-cluster/8.1/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/8.1/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/8.1/cnf/mysql-cluster.cnf b/mysql-cluster/8.1/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/8.1/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/8.1/docker-entrypoint.sh b/mysql-cluster/8.1/docker-entrypoint.sh new file mode 100755 index 000000000..30f975a8c --- /dev/null +++ b/mysql-cluster/8.1/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 8.1.0-1.2.13-cluster" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol8_appstream \ + --enablerepo=mysql-cluster-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/8.2/cnf/my.cnf b/mysql-cluster/8.2/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/8.2/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/8.2/cnf/mysql-cluster.cnf b/mysql-cluster/8.2/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/8.2/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/8.2/docker-entrypoint.sh b/mysql-cluster/8.2/docker-entrypoint.sh new file mode 100755 index 000000000..9c130f143 --- /dev/null +++ b/mysql-cluster/8.2/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image " +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol8_appstream \ + --enablerepo=mysql-cluster-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/8.3/cnf/my.cnf b/mysql-cluster/8.3/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/8.3/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/8.3/cnf/mysql-cluster.cnf b/mysql-cluster/8.3/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/8.3/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/8.3/docker-entrypoint.sh b/mysql-cluster/8.3/docker-entrypoint.sh new file mode 100755 index 000000000..9c130f143 --- /dev/null +++ b/mysql-cluster/8.3/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image " +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-8.4-lts-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-cluster-8.4-lts-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/8.4/cnf/my.cnf b/mysql-cluster/8.4/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/8.4/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/8.4/cnf/mysql-cluster.cnf b/mysql-cluster/8.4/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/8.4/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/8.4/docker-entrypoint.sh b/mysql-cluster/8.4/docker-entrypoint.sh new file mode 100755 index 000000000..1d184f09f --- /dev/null +++ b/mysql-cluster/8.4/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 8.4.7-1.2.23-cluster" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-cluster-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/9.0/cnf/my.cnf b/mysql-cluster/9.0/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/9.0/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/9.0/cnf/mysql-cluster.cnf b/mysql-cluster/9.0/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/9.0/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/9.0/docker-entrypoint.sh b/mysql-cluster/9.0/docker-entrypoint.sh new file mode 100755 index 000000000..9c130f143 --- /dev/null +++ b/mysql-cluster/9.0/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image " +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-cluster-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/9.1/cnf/my.cnf b/mysql-cluster/9.1/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/9.1/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/9.1/cnf/mysql-cluster.cnf b/mysql-cluster/9.1/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/9.1/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/9.1/docker-entrypoint.sh b/mysql-cluster/9.1/docker-entrypoint.sh new file mode 100755 index 000000000..9c130f143 --- /dev/null +++ b/mysql-cluster/9.1/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image " +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-cluster-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/9.2/cnf/my.cnf b/mysql-cluster/9.2/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/9.2/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/9.2/cnf/mysql-cluster.cnf b/mysql-cluster/9.2/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/9.2/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/9.2/docker-entrypoint.sh b/mysql-cluster/9.2/docker-entrypoint.sh new file mode 100755 index 000000000..9c130f143 --- /dev/null +++ b/mysql-cluster/9.2/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image " +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-cluster-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/9.3/cnf/my.cnf b/mysql-cluster/9.3/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/9.3/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/9.3/cnf/mysql-cluster.cnf b/mysql-cluster/9.3/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/9.3/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/9.3/docker-entrypoint.sh b/mysql-cluster/9.3/docker-entrypoint.sh new file mode 100755 index 000000000..9c130f143 --- /dev/null +++ b/mysql-cluster/9.3/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image " +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-cluster-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/9.4/cnf/my.cnf b/mysql-cluster/9.4/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/9.4/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/9.4/cnf/mysql-cluster.cnf b/mysql-cluster/9.4/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/9.4/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/9.4/docker-entrypoint.sh b/mysql-cluster/9.4/docker-entrypoint.sh new file mode 100755 index 000000000..9c130f143 --- /dev/null +++ b/mysql-cluster/9.4/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image " +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-cluster-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060-33061 2202 1186 +CMD ["mysqld"] + diff --git a/mysql-cluster/9.5/cnf/my.cnf b/mysql-cluster/9.5/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/9.5/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/9.5/cnf/mysql-cluster.cnf b/mysql-cluster/9.5/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/9.5/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/9.5/docker-entrypoint.sh b/mysql-cluster/9.5/docker-entrypoint.sh new file mode 100755 index 000000000..9c130f143 --- /dev/null +++ b/mysql-cluster/9.5/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image " +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" <. + +Supported Tags and Respective Dockerfile Links +---------------------------------------------- + +These are tags for some of the optimized MySQL Server Docker images, created and maintained by the MySQL team at Oracle (for a full list, see [the Tags tab of this page](https://hub.docker.com/r/mysql/mysql-server/tags/)). + +- MySQL Server 5.5 (tag: [`5.5`, `5.5.58`, `5.5.58-1.1.2`](https://github.com/mysql/mysql-docker/blob/mysql-server/5.5/Dockerfile)) ([mysql-server/5.5/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-server/5.5/Dockerfile)) + +- MySQL Server 5.6 (tag: [`5.6`, `5.6.38`, `5.6.38-1.1.2`](https://github.com/mysql/mysql-docker/blob/mysql-server/5.6/Dockerfile)) ([mysql-server/5.6/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-server/5.6/Dockerfile)) + +- MySQL Server 5.7, the latest GA (tag: [`5.7`, `5.7.20`, `5.7.20-1.1.2`](https://github.com/mysql/mysql-docker/blob/mysql-server/5.7/Dockerfile)) ([mysql-server/5.7/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-server/5.7/Dockerfile)) + +- MySQL Server 8.0, Release Candidate (tag: [`8.0`, `8.0.3-rc`, `8.0.3-rc-1.1.2`](https://github.com/mysql/mysql-docker/blob/mysql-server/8.0/Dockerfile)) ([mysql-server/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-server/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +We also from time to time publish special MySQL Server images that contain experimental features. Please take a look at the [MySQL Docker image list](https://hub.docker.com/r/mysql/) to see what are available. + +Quick Reference +--------------- + +- *Detailed documentation:* See [Deploying MySQL on Linux with Docker](https://dev.mysql.com/doc/refman/5.7/en/linux-installation-docker.html) in the [MySQL Reference Manual](https://dev.mysql.com/doc/refman/5.7/en/). + +- *Where to file issues:* Please submit a bug report at under the category “MySQL Package Repos and Docker Images”. + +- *Maintained by:* The MySQL team at Oracle + +- *Source of this image:* The [Image repository for the `mysql/mysql-server` container](https://github.com/mysql/mysql-docker) + +- *Supported Docker versions:* The latest stable release is supported. Support for older versions (down to 1.0) is provided on a best-effort basis, but we strongly recommend using the most recent stable Docker version, which this documentation assumes. + +How to Use the MySQL Images +--------------------------- + +### Downloading a MySQL Server Docker Image + +Downloading the server image in a separate step is not strictly necessary; however, performing this before you create your Docker container ensures your local image is up to date. + +To download the MySQL Community Edition image, run this command: + + docker pull mysql/mysql-server:tag + + + +Refer to the list of supported tags above. If `:tag + ` is omitted, the `latest` tag is used, and the image for the latest GA version of MySQL Server is downloaded. + +### Starting a MySQL Server Instance + +Start a new Docker container for the MySQL Community Server with this command: + + docker run --name=mysql1 -d mysql/mysql-server:tag + + + +The `--name` option, for supplying a custom name for your server container (`mysql1` in the example), is optional; if no container name is supplied, a random one is generated. If the Docker image of the specified name and tag has not been downloaded by an earlier `docker pull` or `docker run` command, the image is now downloaded. After download completes, initialization for the container begins, and the container appears in the list of running containers when you run the `docker ps` command; for example: + + shell> docker ps + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + a24888f0d6f4 mysql/mysql-server "/entrypoint.sh my..." 14 seconds ago Up 13 seconds (health: starting) 3306/tcp, 33060/tcp mysql1 + +The container initialization might take some time. When the server is ready for use, the `STATUS` of the container in the output of the `docker ps` command changes from `(health: starting)` to `(healthy)`. + +The `-d` option used in the `docker + run` command above makes the container run in the background. Use this command to monitor the output from the container: + + docker logs mysql1 + + +Once initialization is finished, the command's output is going to contain the random password generated for the root user; check the password with, for example, this command: + + shell> docker logs mysql1 2>&1 | grep GENERATED + GENERATED ROOT PASSWORD: Axegh3kAJyDLaRuBemecis&EShOs + +### Connecting to MySQL Server from within the Container + +Once the server is ready, you can run the `mysql` client within the MySQL Server container you just started and connect it to the MySQL Server. Use the `docker exec -it` command to start a `mysql` client inside the Docker container you have started, like this: + + docker exec -it mysql1 mysql -uroot -p + + +When asked, enter the generated root password (see the instructions above on how to find it). Because the `MYSQL_ONETIME_PASSWORD` option is true by default, after you started the server container with the sample command above and connected a `mysql` client to the server, you must reset the server root password by issuing this statement: + + mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'newpassword'; + + +Substitute `newpassword` with the password of your choice. Once the password is reset, the server is ready for use. + +### Container Shell Access + +To have shell access to your MySQL Server container, use the `docker exec -it` command to start a bash shell inside the container: + + shell> docker exec -it mysql1 bash + bash-4.2# + +You can then run Linux commands inside the container at the bash prompt. + +### Stopping and Deleting a MySQL Container + +To stop the MySQL Server container we have created, use this command: + + docker stop mysql1 + + +`docker stop` sends a SIGTERM signal to the `mysqld` process, so that the server is shut down gracefully. + +Also notice that when the main process of a container (`mysqld` in the case of a MySQL Server container) is stopped, the Docker container stops automatically. + +To start the MySQL Server container again: + + docker start mysql1 + + +To stop and start again the MySQL Server container with a single command: + + docker restart mysql1 + + +To delete the MySQL container, stop it first, and then use the `docker rm` command: + + docker stop mysql1 + + docker rm mysql1 + + +If you want the [Docker volume for the server's data directory](https://dev.mysql.com/doc/refman/5.7/en/docker-mysql-more-topics.html#docker-persisting-data-configuration) to be deleted at the same time, add the `-v` option to the `docker rm` command. + +### More Topics on Deploying MySQL Server with Docker + +For more topics on deploying MySQL Server with Docker like server configuration, persisting data and configuration, and server error log, see [More Topics on Deploying MySQL Server with Docker](https://dev.mysql.com/doc/refman/5.7/en/docker-mysql-more-topics.html) in the MySQL Server manual. + +Docker Environment Variables +---------------------------- + +When you create a MySQL Server container, you can configure the MySQL instance by using the `--env` option (`-e` in short) and specifying one or more of the following environment variables. + +> **Notes** +> +> - None of the variables below has any effect if you mount a data directory that is not empty, as no server initialization is going to be attempted then (see [Persisting Data and Configuration Changes](https://dev.mysql.com/doc/refman/5.7/en/docker-mysql-more-topics.html#docker-persisting-data-configuration) for more details). Any pre-existing contents in the folder, including any old server settings, are not modified during the container startup. +> +> - The boolean variables including `MYSQL_RANDOM_ROOT_PASSWORD`, `MYSQL_ONETIME_PASSWORD`, `MYSQL_ALLOW_EMPTY_PASSWORD`, and `MYSQL_LOG_CONSOLE` are made true by setting them with any strings of non-zero lengths. Therefore, setting them to, for example, “0”, “false”, or “no” does not make them false, but actually makes them true. This is a known issue of the MySQL Server containers. +> +  + +- `MYSQL_RANDOM_ROOT_PASSWORD`: When this variable is true (which is its default state, unless `MYSQL_ROOT_PASSWORD` is set or `MYSQL_ALLOW_EMPTY_PASSWORD` is set to true), a random password for the server's root user is generated when the Docker container is started. The password is printed to `stdout` of the container and can be found by looking at the container’s log. + +- `MYSQL_ONETIME_PASSWORD`: When the variable is true (which is its default state, unless `MYSQL_ROOT_PASSWORD` is set or `MYSQL_ALLOW_EMPTY_PASSWORD` is set to true), the root user's password is set as expired and must be changed before MySQL can be used normally. This variable is only supported for MySQL 5.6 and later. + +- `MYSQL_DATABASE`: This variable allows you to specify the name of a database to be created on image startup. If a user name and a password are supplied with `MYSQL_USER` and `MYSQL_PASSWORD`, the user is created and granted superuser access to this database (corresponding to `GRANT ALL`). The specified database is created by a [CREATE DATABASE IF NOT EXIST](#create-database) statement, so that the variable has no effect if the database already exists. + +- `MYSQL_USER`, `MYSQL_PASSWORD`: These variables are used in conjunction to create a user and set that user's password, and the user is granted superuser permissions for the database specified by the `MYSQL_DATABASE` variable. Both `MYSQL_USER` and `MYSQL_PASSWORD` are required for a user to be created; if any of the two variables is not set, the other is ignored. If both variables are set but `MYSQL_DATABASE` is not, the user is created without any privileges. + + > **Note** + > + > There is no need to use this mechanism to create the root superuser, which is created by default with the password set by either one of the mechanisms discussed in the descriptions for `MYSQL_ROOT_PASSWORD` and `MYSQL_RANDOM_ROOT_PASSWORD`, unless `MYSQL_ALLOW_EMPTY_PASSWORD` is true. + +- `MYSQL_ROOT_HOST`: By default, MySQL creates the `'root'@'localhost'` account. This account can only be connected to from inside the container. To allow root connections from other hosts, set this environment variable. For example, the value `172.17.0.1`, which is the default Docker gateway IP, allows connections from the host machine that runs the container. The option accepts only one entry, but wildcards are allowed (for example, `MYSQL_ROOT_HOST=172.*.*.*` or `MYSQL_ROOT_HOST=%`). + +- `MYSQL_LOG_CONSOLE`: When the variable is true (which is its default state for MySQL 8.0 server containers), the MySQL Server's error log is redirected to `stderr`, so that the error log goes into the Docker container's log and is viewable using the `docker logs` command. + + > **Note** + > + > The variable has no effect if a server configuration file from the host has been mounted (see [Persisting Data and Configuration Changes](https://dev.mysql.com/doc/refman/5.7/en/docker-mysql-more-topics.html#docker-persisting-data-configuration) on bind-mounting a configuration file). + +- `MYSQL_ROOT_PASSWORD`: This variable specifies a password that is set for the MySQL root account. + + > **Warning** + > + > Setting the MySQL root user password on the command line is insecure. As an alternative to specifying the password explicitly, you can set the variable with a container file path for a password file, and then mount a file from your host that contains the password at the container file path. This is still not very secure, as the location of the password file is still exposed. It is preferable to use the default settings of `MYSQL_RANDOM_ROOT_PASSWORD` and `MYSQL_ONETIME_PASSWORD` being both true. + +- `MYSQL_ALLOW_EMPTY_PASSWORD`. Set it to true to allow the container to be started with a blank password for the root user. + + > **Warning** + > + > Setting this variable to true is insecure, because it is going to leave your MySQL instance completely unprotected, allowing anyone to gain complete superuser access. It is preferable to use the default settings of `MYSQL_RANDOM_ROOT_PASSWORD` and `MYSQL_ONETIME_PASSWORD` being both true. diff --git a/mysql-cluster/VERSION b/mysql-cluster/VERSION new file mode 100644 index 000000000..cc04b2b83 --- /dev/null +++ b/mysql-cluster/VERSION @@ -0,0 +1,40 @@ +IMAGE_VERSION=1.2.23-cluster + +# LATEST is always set to the +# current highest release, which is, +# either 'innovation' or an LTS series +# i.e. 9.7, or 10.7 + +LATEST="innovation" + + + +# LATEST_LTS is set to the highest +# LTS series currently being released +# i.e. when 9.7 release will come it +# will be set to 9.7 up till 10.7 and +# then 10.7 and so on + +LATEST_LTS="8.4" + + + +# The value of key should be series +# i.e. 8.0, 8.4, innovation, 9.7, etc. +# do not use any other value for key +# like 'latest-8.4' or 'lts-84', etch + +declare -A MYSQL_CLUSTER_VERSIONS +MYSQL_CLUSTER_VERSIONS["8.0"]=8.0.44 +MYSQL_CLUSTER_VERSIONS["8.4"]=8.4.7 +MYSQL_CLUSTER_VERSIONS["innovation"]=9.5.0 + +declare -A MYSQL_SHELL_VERSIONS +MYSQL_SHELL_VERSIONS["8.0"]=8.0.44 +MYSQL_SHELL_VERSIONS["8.4"]=8.4.7 +MYSQL_SHELL_VERSIONS["innovation"]=9.5.0 + +declare -A FULL_SERVER_VERSIONS +FULL_SERVER_VERSIONS["8.0"]="${MYSQL_CLUSTER_VERSIONS["8.0"]}-${IMAGE_VERSION}" +FULL_SERVER_VERSIONS["8.4"]="${MYSQL_CLUSTER_VERSIONS["8.4"]}-${IMAGE_VERSION}" +FULL_SERVER_VERSIONS["innovation"]="${MYSQL_CLUSTER_VERSIONS["innovation"]}-${IMAGE_VERSION}" diff --git a/mysql-cluster/build.sh b/mysql-cluster/build.sh new file mode 100755 index 000000000..3f756d9c2 --- /dev/null +++ b/mysql-cluster/build.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e +source ./VERSION + +MAJOR_VERSIONS=("${!MYSQL_CLUSTER_VERSIONS[@]}"); [ -n "$1" ] && MAJOR_VERSIONS=("${@:1}") + +for MAJOR_VERSION in "${MAJOR_VERSIONS[@]}"; do + CLUSTER_VERSION=${MYSQL_CLUSTER_VERSIONS[$MAJOR_VERSION]} + MAJOR_VERSION=${CLUSTER_VERSION%.*} + docker build --build-arg http_proxy=$http_proxy --build-arg https_proxy=$http_proxy --build-arg no_proxy=$no_proxy -t mysql/mysql-cluster:$MAJOR_VERSION $MAJOR_VERSION +done diff --git a/mysql-cluster/changelog b/mysql-cluster/changelog new file mode 100644 index 000000000..19c5a34f2 --- /dev/null +++ b/mysql-cluster/changelog @@ -0,0 +1,59 @@ +Changes in 1.1.3 + * Added support for new infoschema system user in 8.0.4 + * Bumped server versions to 5.5.59, 5.6.39, 5.7.21, 8.0.4 + * Bumper cluster versions to 7.5.9, 7.6.4 + +Changes in 1.1.2 (2017-10-16) + * Bumped server versions to 5.5.58, 5.6.38, 5.7.20 + * Bumped Shell 8.0 version to 8.0.3 + +Changes in 1.1.1 (2017-09-22) + * Disable binlog for all entrypoint client commands (#87305) + This was previously only done only for the script to set the root password, + but should be done for all client commands, or group replication will fail + * Add flag for logging to console (#87458) + Setting -e MYSQL_LOG_CONSOLE=true will make the server log to console, so the + server log is available through Docker's log interface. If /etc/my.cnf is + mounted from the host system, this has no effect. On 8.0, this is the default + behavior. + * Ensure both MYSQL_USER and MYSQL_PASSWORD are set (#86982) + Before, setting only one would cause the option to be silently ignored. + * Read password file first and throw error if it is empty (#87025) + Setting MYSQL_ROOT_PASSWORD to an empty string would be rejected, but + setting it to a file with no content would be accepted. Both are now rejected. + * MYSQL_RANDOM_ROOT_PASSWORD and MYSQL_ONETIME_PASSWORD are now set by default. (#87515) + A password option no longer needs to be set explicitly. If none are set, a + random, expired password is set. + * Make root@$MYSQL_ROOT_HOST identical to root@localhost (#86945) + If the MYSQL_ROOT_HOST variable is set we add an additional root user for + the given host. This user was missing the PROXY privilege. We add the + missing privilege so the users are identical. + * MySQL Server 8.0 updated to 8.0.3-rc + * MySQL Shell for 5.7 updated to 1.0.10 + +Changes in 1.1.0 (2017-07-24) + * Fixed broken MYSQL_ONETIME_PASSWORD support (#86523) + The functionality wasn't correctly updated when the entrypoint script was + changed to only create the root@localhost user by default + * Changed control files to be generated from a common template + The control files for each version will be generated by swapping out the few + commands that differ between server versions + * Made PACKAGE_URL an ARG entry, to allow build-time changing + The URL variables can be changed by supplying new ones with --build-arg at + build time + * Added basic healthcheck script + Once database init is complete a flag file will be touched. If this file + exists and mysqladmin ping succeeds, the container is reported as healthy, + meaning it is ready for use + * Database init will now use configured socket setting instead of hardcoded + Using a hardcoded socket could cause init scripts to fail in confusing ways + if the user customized the socket setting + * Added MySQL Shell to supported images + For 5.7 and 8.0, MySQL Shell is installed together with the server. + https://dev.mysql.com/doc/refman/5.7/en/mysql-shell.html + +Known issues: + * For existing databases created with older images/not with Docker, the + healthcheck script will generate an "Access denied for healthchecker@localhost" + message in the server log every time it runs. If connection throttling is + enabled this could eventually cause the healthcheck to fail diff --git a/mysql-cluster/gen_dockerfiles.sh b/mysql-cluster/gen_dockerfiles.sh new file mode 100755 index 000000000..a20b1af62 --- /dev/null +++ b/mysql-cluster/gen_dockerfiles.sh @@ -0,0 +1,131 @@ +#!/bin/bash +# Copyright (c) 2017, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +set -e + +# This script will simply use sed to replace placeholder variables in the +# files in template/ with version-specific variants. + +source ./VERSION + +REPO=https://repo.mysql.com; [ -n "$1" ] && REPO=$1 +MYSQL_VERSION=""; [ -n "$2" ] && MYSQL_VERSION=$2 +SHELL_VERSION=""; [ -n "$3" ] && SHELL_VERSION=$3 +CONFIG_PACKAGE_NAME=mysql80-community-release-el9.rpm; [ -n "$4" ] && CONFIG_PACKAGE_NAME=$4 +CONFIG_PACKAGE_NAME_MINIMAL=mysql-cluster-community-minimal-release-el9.rpm; [ -n "$5" ] && CONFIG_PACKAGE_NAME_MINIMAL=$5 + +REPO_NAME_SERVER=mysql-cluster80-community-minimal; [ -n "$6" ] && REPO_NAME_SERVER=$6 +REPO_NAME_TOOLS=mysql-tools-community; [ -n "$7" ] && REPO_NAME_TOOLS=$7 + +MYSQL_SERVER_PACKAGE_NAME="mysql-cluster-community-server-minimal"; [ -n "$8" ] && MYSQL_SERVER_PACKAGE_NAME=$8 +MYSQL_SHELL_PACKAGE_NAME="mysql-shell"; [ -n "$9" ] && MYSQL_SHELL_PACKAGE_NAME=$9 + +PORTS="3306 33060-33061 2202 1186" + +PASSWORDSET="ALTER USER 'root'@'localhost' IDENTIFIED BY '\${MYSQL_ROOT_PASSWORD}';" + +DATABASE_INIT="\"\$@\" --user=\$MYSQLD_USER --initialize-insecure" + +STARTUP="export MYSQLD_PARENT_PID=\$\$ ; exec \"\$@\" --user=$MYSQLD_USER" + +# MySQL 8.0 supports a call to validate the config, while older versions have it as a side +# effect of running --verbose --help +VALIDATE_CONFIG="output=\$(\"\$@\" --validate-config) || result=\$?" + +# Data directories that must be created with special ownership and permissions when the image is built +PRECREATE_DIRS="/var/lib/mysql /var/lib/mysql-files /var/lib/mysql-keyring /var/run/mysqld" + +process_version() { + MAJOR_VERSION=$1 + MYSQL_SERVER_PACKAGE=${MYSQL_SERVER_PACKAGE_NAME}${SERVER_PKG_SUFFIX} + MYSQL_SHELL_PACKAGE=${MYSQL_SHELL_PACKAGE_NAME}${SHELL_PKG_SUFFIX} + + # Dockerfiles + DOCKERFILE_TEMPLATE=template/Dockerfile + if [[ "${MAJOR_VERSION}" =~ 7\.(5|6) ]]; then + DOCKERFILE_TEMPLATE=template/Dockerfile-pre8 + fi + + # Dockerfile_spec.rb + if [ ! -d "${MAJOR_VERSION}" ]; then + mkdir "${MAJOR_VERSION}" + fi + + sed 's#%%MYSQL_SERVER_PACKAGE%%#'"${MYSQL_SERVER_PACKAGE}"'#g' $DOCKERFILE_TEMPLATE > tmpfile + sed -i 's#%%REPO%%#'"${REPO}"'#g' tmpfile + REPO_VERSION=${MAJOR_VERSION//\./} + sed -i 's#%%REPO_VERSION%%#'"${REPO_VERSION}"'#g' tmpfile + + sed -i 's#%%CONFIG_PACKAGE_NAME%%#'"${CONFIG_PACKAGE_NAME}"'#g' tmpfile + sed -i 's#%%CONFIG_PACKAGE_NAME_MINIMAL%%#'"${CONFIG_PACKAGE_NAME_MINIMAL}"'#g' tmpfile + sed -i 's#%%REPO_NAME_SERVER%%#'"${REPO_NAME_SERVER}"'#g' tmpfile + sed -i 's#%%REPO_NAME_TOOLS%%#'"${REPO_NAME_TOOLS}"'#g' tmpfile + sed -i 's#%%MYSQL_SHELL_PACKAGE%%#'"${MYSQL_SHELL_PACKAGE}"'#g' tmpfile + sed -i 's/%%PORTS%%/'"${PORTS}"'/g' tmpfile + mv tmpfile ${MAJOR_VERSION}/Dockerfile + + # Dockerfile_spec.rb + if [ ! -d "${MAJOR_VERSION}/inspec" ]; then + mkdir "${MAJOR_VERSION}/inspec" + fi + + sed 's#%%MYSQL_VERSION%%#'"${MYSQL_VERSION}"'#g' template/control.rb > tmpFile + sed -i 's#%%MYSQL_SERVER_PACKAGE_NAME%%#'"${MYSQL_SERVER_PACKAGE_NAME}"'#g' tmpFile + sed -i 's#%%MYSQL_SHELL_PACKAGE_NAME%%#'"${MYSQL_SHELL_PACKAGE_NAME}"'#g' tmpFile + + sed -i 's#%%MAJOR_VERSION%%#'"${MAJOR_VERSION}"'#g' tmpFile + sed -i 's#%%MYSQL_SHELL_VERSION%%#'"${SHELL_VERSION}"'#g' tmpFile + + sed -i 's#%%PORTS%%#'"1186/tcp, 2202/tcp, 3306/tcp, 33060-33061/tcp"'#g' tmpFile + mv tmpFile "${MAJOR_VERSION}/inspec/control.rb" + + # Entrypoint + sed 's#%%PASSWORDSET%%#'"${PASSWORDSET}"'#g' template/docker-entrypoint.sh > tmpfile + sed -i 's#%%STARTUP%%#'"${STARTUP}"'#g' tmpfile + sed -i 's#%%FULL_SERVER_VERSION%%#'"${FULL_SERVER_VERSIONS[${MAJOR_VERSION}]}"'#g' tmpfile + sed -i 's#%%VALIDATE_CONFIG%%#'"${VALIDATE_CONFIG}"'#g' tmpfile + mv tmpfile ${MAJOR_VERSION}/docker-entrypoint.sh + chmod +x ${MAJOR_VERSION}/docker-entrypoint.sh + + # Healthcheck + cp template/healthcheck.sh ${MAJOR_VERSION}/ + chmod +x ${MAJOR_VERSION}/healthcheck.sh + + # Build-time preparation script + sed 's#%%PRECREATE_DIRS%%#'"${PRECREATE_DIRS}"'#g' template/prepare-image.sh > tmpfile + mv tmpfile ${MAJOR_VERSION}/prepare-image.sh + chmod +x ${MAJOR_VERSION}/prepare-image.sh + + # Copy cnf files + cp -r template/cnf ${MAJOR_VERSION}/ +} + +if [ -n "$MYSQL_VERSION" ]; then + MAJOR_VERSION=$(echo $MYSQL_VERSION | cut -d'.' -f'1,2') + SERVER_PKG_SUFFIX="-${MYSQL_VERSION}" + SHELL_PKG_SUFFIX="-${SHELL_VERSION}" + process_version $MAJOR_VERSION +else + for MAJOR_VERSION in "${!MYSQL_CLUSTER_VERSIONS[@]}" + do + SHELL_VERSION="${MYSQL_SHELL_VERSIONS[$MAJOR_VERSION]}" + SHELL_PKG_SUFFIX="-${SHELL_VERSION}" + SERVER_PKG_SUFFIX="-${MYSQL_CLUSTER_VERSIONS[$MAJOR_VERSION]}" + + process_version $MAJOR_VERSION + done +fi + diff --git a/mysql-cluster/tag.sh b/mysql-cluster/tag.sh new file mode 100755 index 000000000..1db40056c --- /dev/null +++ b/mysql-cluster/tag.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e +source VERSION + +MAJOR_VERSIONS=("${!MYSQL_CLUSTER_VERSIONS[@]}"); [ -n "$1" ] && MAJOR_VERSIONS=("${@:1}") + +for MAJOR_VERSION in "${MAJOR_VERSIONS[@]}"; do + CLUSTER_VERSION=${MYSQL_CLUSTER_VERSIONS[$MAJOR_VERSION]} + FULL_VERSION=${FULL_SERVER_VERSIONS[$MAJOR_VERSION]} + MAJOR_VERSION=${CLUSTER_VERSION%.*} + TAGS="$MAJOR_VERSION $CLUSTER_VERSION $FULL_VERSION" + + if [ "$MAJOR_VERSION" = "$LATEST" ]; then + TAGS="latest $TAGS" + fi + + echo $TAGS +done diff --git a/mysql-cluster/template/Dockerfile b/mysql-cluster/template/Dockerfile new file mode 100644 index 000000000..e017eae24 --- /dev/null +++ b/mysql-cluster/template/Dockerfile @@ -0,0 +1,47 @@ +# Copyright (c) 2017, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_SERVER_PACKAGE=%%MYSQL_SERVER_PACKAGE%% +ARG MYSQL_SHELL_PACKAGE=%%MYSQL_SHELL_PACKAGE%% + +# Setup repositories for minimal packages (all versions) +RUN rpm -U %%REPO%%/%%CONFIG_PACKAGE_NAME_MINIMAL%% \ + && rpm -U %%REPO%%/%%CONFIG_PACKAGE_NAME%% + +# Install server and shell 8.0 +RUN microdnf update && echo "[main]" > /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=%%REPO_NAME_TOOLS%% $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=%%REPO_NAME_SERVER%% $MYSQL_SERVER_PACKAGE \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE %%PORTS%% +CMD ["mysqld"] + diff --git a/mysql-cluster/template/Dockerfile-pre8 b/mysql-cluster/template/Dockerfile-pre8 new file mode 100644 index 000000000..f8b54d957 --- /dev/null +++ b/mysql-cluster/template/Dockerfile-pre8 @@ -0,0 +1,45 @@ +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +FROM container-registry.oracle.com/os/oraclelinux:7-slim + +ARG MYSQL_SERVER_PACKAGE=%%MYSQL_SERVER_PACKAGE%% +ARG MYSQL_SHELL_PACKAGE=%%MYSQL_SHELL_PACKAGE%% + +# Setup repositories for minimal packages (all versions) +RUN rpm -U %%REPO%%/mysql-cluster-community-minimal-release-el7.rpm \ + && rpm -U %%REPO%%/mysql80-community-release-el7.rpm + +# Install server and shell 8.0 +RUN yum install -y $MYSQL_SHELL_PACKAGE \ + && yum install -y $MYSQL_SERVER_PACKAGE --enablerepo=mysql-cluster%%REPO_VERSION%%-community-minimal\ + && yum clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +COPY cnf/my.cnf /etc/ +COPY cnf/mysql-cluster.cnf /etc/ + +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE %%PORTS%% +CMD ["mysqld"] + diff --git a/mysql-cluster/template/cnf/my.cnf b/mysql-cluster/template/cnf/my.cnf new file mode 100644 index 000000000..ec98b2dc1 --- /dev/null +++ b/mysql-cluster/template/cnf/my.cnf @@ -0,0 +1,22 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[mysqld] +ndbcluster +ndb-connectstring=192.168.0.2 +user=mysql + +[mysql_cluster] +ndb-connectstring=192.168.0.2 diff --git a/mysql-cluster/template/cnf/mysql-cluster.cnf b/mysql-cluster/template/cnf/mysql-cluster.cnf new file mode 100644 index 000000000..16f79f1c0 --- /dev/null +++ b/mysql-cluster/template/cnf/mysql-cluster.cnf @@ -0,0 +1,39 @@ +# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +[ndbd default] +NoOfReplicas=2 +DataMemory=80M +IndexMemory=18M + + +[ndb_mgmd] +NodeId=1 +hostname=192.168.0.2 +datadir=/var/lib/mysql + +[ndbd] +NodeId=2 +hostname=192.168.0.3 +datadir=/var/lib/mysql + +[ndbd] +NodeId=3 +hostname=192.168.0.4 +datadir=/var/lib/mysql + +[mysqld] +NodeId=4 +hostname=192.168.0.10 diff --git a/mysql-cluster/template/control.rb b/mysql-cluster/template/control.rb new file mode 100644 index 000000000..9582baf4b --- /dev/null +++ b/mysql-cluster/template/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /mysqld/ } + its('images') { should cmp /mysql-cluster:%%MAJOR_VERSION%%/ } + its('names') { should include "mysql-cluster-%%MAJOR_VERSION%%" } + end +end +control 'packages' do + impact 0.5 + describe package('%%MYSQL_SERVER_PACKAGE_NAME%%') do + it { should be_installed } + its ('version') { should match '%%MYSQL_VERSION%%.*' } + end + describe package('%%MYSQL_SHELL_PACKAGE_NAME%%') do + it { should be_installed } + its ('version') { should match '%%MYSQL_SHELL_VERSION%%.*' } + end +end diff --git a/mysql-cluster/template/docker-entrypoint.sh b/mysql-cluster/template/docker-entrypoint.sh new file mode 100644 index 000000000..d8ecca687 --- /dev/null +++ b/mysql-cluster/template/docker-entrypoint.sh @@ -0,0 +1,264 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image %%FULL_SERVER_VERSION%%" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + %%VALIDATE_CONFIG%% + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + if [ ! -z %%STARTUP_WAIT%% ]; + then + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="%%PASSWORDSET%%" + else + ROOTCREATE="%%PASSWORDSET%% \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" </dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U https://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y \ + --enablerepo=mysql80-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/8.0/README.md b/mysql-router/8.0/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/8.0/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/8.0/inspec/control.rb b/mysql-router/8.0/inspec/control.rb new file mode 100644 index 000000000..ed523188e --- /dev/null +++ b/mysql-router/8.0/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:8.0/ } + its('names') { should include "mysql-router-8.0" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '8.0.44.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '8.0.44.*' } + end +end diff --git a/mysql-router/8.0/run.sh b/mysql-router/8.0/run.sh new file mode 100755 index 000000000..79bb35080 --- /dev/null +++ b/mysql-router/8.0/run.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Copyright (c) 2018, 2024, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [[ -n $MYSQL_USER_FILE && -f $MYSQL_USER_FILE ]]; then + MYSQL_USER=$(cat $MYSQL_USER_FILE) +fi + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || (-z $MYSQL_PASSWORD && -z $MYSQL_PASSWORD_FILE) ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER or MYSQL_USER_FILE" + echo " MYSQL_PASSWORD or MYSQL_PASSWORD_FILE" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS" + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" > "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" > "$PASSFILE" + fi + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" <"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + rm "$DEFAULTS_EXTRA_FILE" + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm $PASSFILE +else + exec "$@" +fi diff --git a/mysql-router/8.1/Dockerfile b/mysql-router/8.1/Dockerfile new file mode 100644 index 000000000..8f550f123 --- /dev/null +++ b/mysql-router/8.1/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:8-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-8.1.0 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-8.1.0 +ARG CONFIG_PACKAGE_NAME=mysql80-community-release-el8.rpm +ARG REPO_NAME_SERVER=mysql-innovation-community +ARG REPO_NAME_TOOLS=mysql-tools-innovation-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U http://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-innovation-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-innovation-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/8.1/README.md b/mysql-router/8.1/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/8.1/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/8.1/inspec/control.rb b/mysql-router/8.1/inspec/control.rb new file mode 100644 index 000000000..ca9ebf141 --- /dev/null +++ b/mysql-router/8.1/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:8.1/ } + its('names') { should include "mysql-router-8.1" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '8.1.0.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '8.1.0.*' } + end +end diff --git a/mysql-router/8.1/run.sh b/mysql-router/8.1/run.sh new file mode 100755 index 000000000..f806c1afe --- /dev/null +++ b/mysql-router/8.1/run.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || -z $MYSQL_PASSWORD ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER" + echo " MYSQL_PASSWORD" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS " + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + echo "$MYSQL_PASSWORD" > "$PASSFILE" + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm -f "$PASSFILE" + rm -f "$DEFAULTS_EXTRA_FILE" + unset DEFAULTS_EXTRA_FILE +else + exec "$@" +fi diff --git a/mysql-router/8.2/Dockerfile b/mysql-router/8.2/Dockerfile new file mode 100644 index 000000000..fac89eae1 --- /dev/null +++ b/mysql-router/8.2/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:8-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-8.2.0 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-8.2.0 +ARG CONFIG_PACKAGE_NAME=mysql80-community-release-el8.rpm +ARG REPO_NAME_SERVER=mysql-innovation-community +ARG REPO_NAME_TOOLS=mysql-tools-innovation-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U http://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-innovation-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-innovation-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/8.2/README.md b/mysql-router/8.2/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/8.2/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/8.2/inspec/control.rb b/mysql-router/8.2/inspec/control.rb new file mode 100644 index 000000000..7df5082a3 --- /dev/null +++ b/mysql-router/8.2/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:8.2/ } + its('names') { should include "mysql-router-8.2" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '8.2.0.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '8.2.0.*' } + end +end diff --git a/mysql-router/8.2/run.sh b/mysql-router/8.2/run.sh new file mode 100755 index 000000000..f806c1afe --- /dev/null +++ b/mysql-router/8.2/run.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || -z $MYSQL_PASSWORD ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER" + echo " MYSQL_PASSWORD" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS " + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + echo "$MYSQL_PASSWORD" > "$PASSFILE" + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm -f "$PASSFILE" + rm -f "$DEFAULTS_EXTRA_FILE" + unset DEFAULTS_EXTRA_FILE +else + exec "$@" +fi diff --git a/mysql-router/8.3/Dockerfile b/mysql-router/8.3/Dockerfile new file mode 100644 index 000000000..51338541c --- /dev/null +++ b/mysql-router/8.3/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:8-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-8.3.0 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-8.3.0 +ARG CONFIG_PACKAGE_NAME=mysql80-community-release-el8.rpm +ARG REPO_NAME_SERVER=mysql-innovation-community +ARG REPO_NAME_TOOLS=mysql-tools-innovation-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U http://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-innovation-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-innovation-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/8.3/README.md b/mysql-router/8.3/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/8.3/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/8.3/inspec/control.rb b/mysql-router/8.3/inspec/control.rb new file mode 100644 index 000000000..7b00c4120 --- /dev/null +++ b/mysql-router/8.3/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:8.3/ } + its('names') { should include "mysql-router-8.3" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '8.3.0.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '8.3.0.*' } + end +end diff --git a/mysql-router/8.3/run.sh b/mysql-router/8.3/run.sh new file mode 100755 index 000000000..f806c1afe --- /dev/null +++ b/mysql-router/8.3/run.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || -z $MYSQL_PASSWORD ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER" + echo " MYSQL_PASSWORD" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS " + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + echo "$MYSQL_PASSWORD" > "$PASSFILE" + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm -f "$PASSFILE" + rm -f "$DEFAULTS_EXTRA_FILE" + unset DEFAULTS_EXTRA_FILE +else + exec "$@" +fi diff --git a/mysql-router/8.4/Dockerfile b/mysql-router/8.4/Dockerfile new file mode 100644 index 000000000..cc806ad31 --- /dev/null +++ b/mysql-router/8.4/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-8.4.7 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-8.4.7 +ARG CONFIG_PACKAGE_NAME=mysql84-community-release-el9.rpm +ARG REPO_NAME_SERVER=mysql-8.4-lts-community +ARG REPO_NAME_TOOLS=mysql-tools-8.4-lts-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U https://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y \ + --enablerepo=mysql-8.4-lts-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-8.4-lts-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/8.4/README.md b/mysql-router/8.4/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/8.4/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/8.4/inspec/control.rb b/mysql-router/8.4/inspec/control.rb new file mode 100644 index 000000000..85f4d3ebb --- /dev/null +++ b/mysql-router/8.4/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:8.4/ } + its('names') { should include "mysql-router-8.4" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '8.4.7.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '8.4.7.*' } + end +end diff --git a/mysql-router/8.4/run.sh b/mysql-router/8.4/run.sh new file mode 100755 index 000000000..79bb35080 --- /dev/null +++ b/mysql-router/8.4/run.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Copyright (c) 2018, 2024, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [[ -n $MYSQL_USER_FILE && -f $MYSQL_USER_FILE ]]; then + MYSQL_USER=$(cat $MYSQL_USER_FILE) +fi + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || (-z $MYSQL_PASSWORD && -z $MYSQL_PASSWORD_FILE) ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER or MYSQL_USER_FILE" + echo " MYSQL_PASSWORD or MYSQL_PASSWORD_FILE" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS" + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" > "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" > "$PASSFILE" + fi + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" <"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + rm "$DEFAULTS_EXTRA_FILE" + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm $PASSFILE +else + exec "$@" +fi diff --git a/mysql-router/9.0/Dockerfile b/mysql-router/9.0/Dockerfile new file mode 100644 index 000000000..50c541c6e --- /dev/null +++ b/mysql-router/9.0/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-9.0.1 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-9.0.1 +ARG CONFIG_PACKAGE_NAME=mysql84-community-release-el9.rpm +ARG REPO_NAME_SERVER=mysql-innovation-community +ARG REPO_NAME_TOOLS=mysql-tools-innovation-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U http://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y \ + --enablerepo=mysql-innovation-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-innovation-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/9.0/README.md b/mysql-router/9.0/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/9.0/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/9.0/inspec/control.rb b/mysql-router/9.0/inspec/control.rb new file mode 100644 index 000000000..6ff21399b --- /dev/null +++ b/mysql-router/9.0/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:9.0/ } + its('names') { should include "mysql-router-9.0" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '9.0.1.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '9.0.1.*' } + end +end diff --git a/mysql-router/9.0/run.sh b/mysql-router/9.0/run.sh new file mode 100755 index 000000000..f806c1afe --- /dev/null +++ b/mysql-router/9.0/run.sh @@ -0,0 +1,101 @@ +#!/bin/bash +# Copyright (c) 2018, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || -z $MYSQL_PASSWORD ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER" + echo " MYSQL_PASSWORD" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS " + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + echo "$MYSQL_PASSWORD" > "$PASSFILE" + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm -f "$PASSFILE" + rm -f "$DEFAULTS_EXTRA_FILE" + unset DEFAULTS_EXTRA_FILE +else + exec "$@" +fi diff --git a/mysql-router/9.1/Dockerfile b/mysql-router/9.1/Dockerfile new file mode 100644 index 000000000..9270f8cc7 --- /dev/null +++ b/mysql-router/9.1/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-9.1.0 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-9.1.0 +ARG CONFIG_PACKAGE_NAME=mysql84-community-release-el9.rpm +ARG REPO_NAME_SERVER=mysql-innovation-community +ARG REPO_NAME_TOOLS=mysql-tools-innovation-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U http://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y \ + --enablerepo=mysql-innovation-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-innovation-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/9.1/README.md b/mysql-router/9.1/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/9.1/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/9.1/inspec/control.rb b/mysql-router/9.1/inspec/control.rb new file mode 100644 index 000000000..f447dc6d8 --- /dev/null +++ b/mysql-router/9.1/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:9.1/ } + its('names') { should include "mysql-router-9.1" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '9.1.0.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '9.1.0.*' } + end +end diff --git a/mysql-router/9.1/run.sh b/mysql-router/9.1/run.sh new file mode 100755 index 000000000..79bb35080 --- /dev/null +++ b/mysql-router/9.1/run.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Copyright (c) 2018, 2024, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [[ -n $MYSQL_USER_FILE && -f $MYSQL_USER_FILE ]]; then + MYSQL_USER=$(cat $MYSQL_USER_FILE) +fi + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || (-z $MYSQL_PASSWORD && -z $MYSQL_PASSWORD_FILE) ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER or MYSQL_USER_FILE" + echo " MYSQL_PASSWORD or MYSQL_PASSWORD_FILE" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS" + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" > "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" > "$PASSFILE" + fi + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" <"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + rm "$DEFAULTS_EXTRA_FILE" + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm $PASSFILE +else + exec "$@" +fi diff --git a/mysql-router/9.2/Dockerfile b/mysql-router/9.2/Dockerfile new file mode 100644 index 000000000..cc735776e --- /dev/null +++ b/mysql-router/9.2/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-9.2.0 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-9.2.0 +ARG CONFIG_PACKAGE_NAME=mysql84-community-release-el9.rpm +ARG REPO_NAME_SERVER=mysql-innovation-community +ARG REPO_NAME_TOOLS=mysql-tools-innovation-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U https://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y \ + --enablerepo=mysql-innovation-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-innovation-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/9.2/README.md b/mysql-router/9.2/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/9.2/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/9.2/inspec/control.rb b/mysql-router/9.2/inspec/control.rb new file mode 100644 index 000000000..8e41e14eb --- /dev/null +++ b/mysql-router/9.2/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:9.2/ } + its('names') { should include "mysql-router-9.2" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '9.2.0.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '9.2.0.*' } + end +end diff --git a/mysql-router/9.2/run.sh b/mysql-router/9.2/run.sh new file mode 100755 index 000000000..79bb35080 --- /dev/null +++ b/mysql-router/9.2/run.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Copyright (c) 2018, 2024, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [[ -n $MYSQL_USER_FILE && -f $MYSQL_USER_FILE ]]; then + MYSQL_USER=$(cat $MYSQL_USER_FILE) +fi + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || (-z $MYSQL_PASSWORD && -z $MYSQL_PASSWORD_FILE) ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER or MYSQL_USER_FILE" + echo " MYSQL_PASSWORD or MYSQL_PASSWORD_FILE" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS" + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" > "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" > "$PASSFILE" + fi + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" <"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + rm "$DEFAULTS_EXTRA_FILE" + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm $PASSFILE +else + exec "$@" +fi diff --git a/mysql-router/9.3/Dockerfile b/mysql-router/9.3/Dockerfile new file mode 100644 index 000000000..75564047c --- /dev/null +++ b/mysql-router/9.3/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-9.3.0 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-9.3.0 +ARG CONFIG_PACKAGE_NAME=mysql84-community-release-el9.rpm +ARG REPO_NAME_SERVER=mysql-innovation-community +ARG REPO_NAME_TOOLS=mysql-tools-innovation-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U https://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y \ + --enablerepo=mysql-innovation-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-innovation-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/9.3/README.md b/mysql-router/9.3/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/9.3/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/9.3/inspec/control.rb b/mysql-router/9.3/inspec/control.rb new file mode 100644 index 000000000..d9c059bca --- /dev/null +++ b/mysql-router/9.3/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:9.3/ } + its('names') { should include "mysql-router-9.3" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '9.3.0.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '9.3.0.*' } + end +end diff --git a/mysql-router/9.3/run.sh b/mysql-router/9.3/run.sh new file mode 100755 index 000000000..79bb35080 --- /dev/null +++ b/mysql-router/9.3/run.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Copyright (c) 2018, 2024, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [[ -n $MYSQL_USER_FILE && -f $MYSQL_USER_FILE ]]; then + MYSQL_USER=$(cat $MYSQL_USER_FILE) +fi + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || (-z $MYSQL_PASSWORD && -z $MYSQL_PASSWORD_FILE) ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER or MYSQL_USER_FILE" + echo " MYSQL_PASSWORD or MYSQL_PASSWORD_FILE" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS" + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" > "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" > "$PASSFILE" + fi + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" <"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + rm "$DEFAULTS_EXTRA_FILE" + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm $PASSFILE +else + exec "$@" +fi diff --git a/mysql-router/9.4/Dockerfile b/mysql-router/9.4/Dockerfile new file mode 100644 index 000000000..b7a4fecee --- /dev/null +++ b/mysql-router/9.4/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-9.4.0 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-9.4.0 +ARG CONFIG_PACKAGE_NAME=mysql84-community-release-el9.rpm +ARG REPO_NAME_SERVER=mysql-innovation-community +ARG REPO_NAME_TOOLS=mysql-tools-innovation-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U https://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y \ + --enablerepo=mysql-innovation-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-innovation-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/9.4/README.md b/mysql-router/9.4/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/9.4/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/9.4/inspec/control.rb b/mysql-router/9.4/inspec/control.rb new file mode 100644 index 000000000..eeea59c38 --- /dev/null +++ b/mysql-router/9.4/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:9.4/ } + its('names') { should include "mysql-router-9.4" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '9.4.0.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '9.4.0.*' } + end +end diff --git a/mysql-router/9.4/run.sh b/mysql-router/9.4/run.sh new file mode 100755 index 000000000..79bb35080 --- /dev/null +++ b/mysql-router/9.4/run.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Copyright (c) 2018, 2024, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [[ -n $MYSQL_USER_FILE && -f $MYSQL_USER_FILE ]]; then + MYSQL_USER=$(cat $MYSQL_USER_FILE) +fi + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || (-z $MYSQL_PASSWORD && -z $MYSQL_PASSWORD_FILE) ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER or MYSQL_USER_FILE" + echo " MYSQL_PASSWORD or MYSQL_PASSWORD_FILE" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS" + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" > "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" > "$PASSFILE" + fi + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" <"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + rm "$DEFAULTS_EXTRA_FILE" + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm $PASSFILE +else + exec "$@" +fi diff --git a/mysql-router/9.5/Dockerfile b/mysql-router/9.5/Dockerfile new file mode 100644 index 000000000..aea7149d4 --- /dev/null +++ b/mysql-router/9.5/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_CLIENT_PACKAGE=mysql-community-client-9.5.0 +ARG MYSQL_ROUTER_PACKAGE=mysql-router-community-9.5.0 +ARG CONFIG_PACKAGE_NAME=mysql84-community-release-el9.rpm +ARG REPO_NAME_SERVER=mysql-innovation-community +ARG REPO_NAME_TOOLS=mysql-tools-innovation-community + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U https://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/$CONFIG_PACKAGE_NAME \ + && microdnf install -y \ + --enablerepo=mysql-innovation-community $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=mysql-tools-innovation-community $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/9.5/README.md b/mysql-router/9.5/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/9.5/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/9.5/inspec/control.rb b/mysql-router/9.5/inspec/control.rb new file mode 100644 index 000000000..8a56244bc --- /dev/null +++ b/mysql-router/9.5/inspec/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:9.5/ } + its('names') { should include "mysql-router-9.5" } + end +end +control 'packages' do + impact 0.5 + describe package('mysql-community-client') do + it { should be_installed } + its ('version') { should match '9.5.0.*' } + end + describe package('mysql-router-community') do + it { should be_installed } + its ('version') { should match '9.5.0.*' } + end +end diff --git a/mysql-router/9.5/run.sh b/mysql-router/9.5/run.sh new file mode 100755 index 000000000..79bb35080 --- /dev/null +++ b/mysql-router/9.5/run.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Copyright (c) 2018, 2024, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [[ -n $MYSQL_USER_FILE && -f $MYSQL_USER_FILE ]]; then + MYSQL_USER=$(cat $MYSQL_USER_FILE) +fi + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || (-z $MYSQL_PASSWORD && -z $MYSQL_PASSWORD_FILE) ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER or MYSQL_USER_FILE" + echo " MYSQL_PASSWORD or MYSQL_PASSWORD_FILE" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS" + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" > "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" > "$PASSFILE" + fi + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" <"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + rm "$DEFAULTS_EXTRA_FILE" + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm $PASSFILE +else + exec "$@" +fi diff --git a/mysql-router/README.md b/mysql-router/README.md new file mode 100644 index 000000000..0f2711ba5 --- /dev/null +++ b/mysql-router/README.md @@ -0,0 +1,88 @@ +![logo](https://www.mysql.com/common/logos/logo-mysql-170x115.png) + +# What is MySQL Router? + +MySQL Router is part of InnoDB cluster, and is lightweight middleware that +provides transparent routing between your application and back-end MySQL +Servers. It can be used for a wide variety of use cases, such as providing high +availability and scalability by effectively routing database traffic to +appropriate back-end MySQL Servers. The pluggable architecture also enables +developers to extend MySQL Router for custom use cases. + +# Supported Tags and Respective Dockerfile Links + +* MySQL Router 8.0 (tag: [`latest`, `8.0`](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) ([mysql-router/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-router/8.0/Dockerfile)) + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that non-GA releases are for preview purposes only and should not be used in production setups. + +# How to Use the MySQL Router Images + +The image currently uses the following mandatory variables: + +| Variable | Description | +| ------------------------ | ------------------------------------------- | +| MYSQL_HOST | MySQL host to connect to | +| MYSQL_PORT | Port to use | +| MYSQL_USER | User to connect with | +| MYSQL_PASSWORD | Password to connect with | + +Running in a container requires a working InnoDB cluster. + +The image uses the following optional variables: + +| Variable | Description | +| ------------------------------------ | ------------------------------------------- | +| MYSQL_INNODB_CLUSTER_MEMBERS | Wait for at least this number of cluster instances to be ONLINE | +| MYSQL_CREATE_ROUTER_USER | Whether to create a new account for the Router to use when it's running. Defaults to 1, set to 0 to disable. | +| MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS | Additional command line options applied while bootstrapping + +If supplied the run script waits for the given mysql host to be up, the InnoDB cluster to have +MYSQL_INNODB_CLUSTER_MEMBERS members and then uses the given server for its +bootstrap mode +[Bootstrapping](https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-deploying-bootstrapping.html). + +The image can be run via: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -e MYSQL_INNODB_CLUSTER_MEMBERS=3 -ti mysql/mysql-router +``` + +Additional command line options for running MySQL Router after bootstrap can be passed a command options. For instance you can use a config file from your home directory like this: + +``` +docker run -e MYSQL_HOST=localhost -e MYSQL_PORT=3306 -e MYSQL_USER=mysql -e MYSQL_PASSWORD=mysql -ti -v $HOME/router-extra.conf:/tmp/router-extra.conf mysql/mysql-router mysqlrouter --extra-config=/tmp/router-extra.conf +``` + +It can be verified by typing: + +``` +docker ps +``` + +The following output should be displayed: + +``` +4954b1c80be1 mysql-router:8.0 "/run.sh mysqlrouter" About a minute ago Up About a minute (healthy) 6447/tcp, 6448/tcp, 0.0.0.0:6446->6446/tcp, 6449/tcp innodbcluster_mysql-router_1 +``` + +By default the container will run as user 999:999 which maps to mysqlrouter:mysqlrouter inside the container. + +# Exposed Ports + +The following TCP ports are exposed by the MySQL Router container: + +| Port | Description +| ----- | --------------------------------------------------------------------------------------- | +| 6446 | R/W connection port. Clients that connect to this port will be forwarded to the PRIMARY | +| 6447 | R/O connection port. Clients that connect to this port will be forwarded to a SECONDARY | +| 6448 | X Protocol R/W connection port. R/W port for X protocol client connections | +| 6449 | X Protocol R/O connection port. R/O port for X protocol client connections | +| 8443 | HTTPS REST interface port. | + +For more information about the REST interface API, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-rest-api-reference.html + +For full usage documentation, see: + +https://dev.mysql.com/doc/mysql-router/8.0/en/mysql-router-installation-docker.html diff --git a/mysql-router/VERSION b/mysql-router/VERSION new file mode 100644 index 000000000..27e422f88 --- /dev/null +++ b/mysql-router/VERSION @@ -0,0 +1,43 @@ +IMAGE_VERSION=1.0.23-router + +# LATEST is always set to the +# current highest release, which is, +# either 'innovation' or an LTS series +# i.e. 9.7, or 10.7 + +LATEST="innovation" + + + +# LATEST_LTS is set to the highest +# LTS series currently being released +# i.e. when 9.7 release will come it +# will be set to 9.7 up till 10.7 and +# then 10.7 and so on + +LATEST_LTS="8.4" + + + +# The value of key should be series +# i.e. 8.0, 8.4, innovation, 9.7, etc. +# do not use any other value for key +# like 'latest-8.4' or 'lts-84', etch + +declare -A MYSQL_ROUTER_VERSIONS WEEKLY_ROUTER_VERSIONS +MYSQL_ROUTER_VERSIONS["8.0"]=8.0.44 +MYSQL_ROUTER_VERSIONS["8.4"]=8.4.7 +MYSQL_ROUTER_VERSIONS["innovation"]=9.5.0 + +WEEKLY_ROUTER_VERSIONS["8.0"]=8.0.44 +WEEKLY_ROUTER_VERSIONS["8.4"]=8.4.7 +WEEKLY_ROUTER_VERSIONS["innovation"]=9.5.0 + +declare -A MYSQL_SERVER_VERSIONS WEEKLY_SERVER_VERSIONS +MYSQL_SERVER_VERSIONS["8.0"]=8.0.44 +MYSQL_SERVER_VERSIONS["8.4"]=8.4.7 +MYSQL_SERVER_VERSIONS["innovation"]=9.5.0 + +WEEKLY_SERVER_VERSIONS["8.0"]=8.0.44 +WEEKLY_SERVER_VERSIONS["8.4"]=8.4.7 +WEEKLY_SERVER_VERSIONS["innovation"]=9.5.0 diff --git a/mysql-router/build.sh b/mysql-router/build.sh new file mode 100755 index 000000000..faff82aca --- /dev/null +++ b/mysql-router/build.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# Copyright (c) 2018, 2023 Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e +source ./VERSION + +ARCH=amd64; [ -n "$1" ] && ARCH=$1 +WEEKLY=''; [ -n "$2" ] && WEEKLY=$2 +MAJOR_VERSIONS=("${!MYSQL_ROUTER_VERSIONS[@]}"); [ -n "$3" ] && MAJOR_VERSIONS=("${@:3}") + +for MAJOR_VERSION in "${MAJOR_VERSIONS[@]}"; do + if [ "$WEEKLY" == "1" ]; then + ROUTER_VERSION=${WEEKLY_ROUTER_VERSIONS["${MAJOR_VERSION}"]} + else + ROUTER_VERSION=${MYSQL_ROUTER_VERSIONS["${MAJOR_VERSION}"]} + fi + MAJOR_VERSION=${ROUTER_VERSION%.*} + docker build --build-arg http_proxy=$http_proxy --build-arg https_proxy=$http_proxy --build-arg no_proxy=$no_proxy -t mysql/mysql-router:$MAJOR_VERSION-$ARCH $MAJOR_VERSION +done diff --git a/mysql-router/gen_dockerfiles.sh b/mysql-router/gen_dockerfiles.sh new file mode 100755 index 000000000..f623794e7 --- /dev/null +++ b/mysql-router/gen_dockerfiles.sh @@ -0,0 +1,47 @@ +#!/bin/bash +set -x +set -e + +source ./VERSION + +REPO=https://repo.mysql.com; [ -n "$1" ] && REPO=$1 +CONFIG_PACKAGE_NAME=mysql80-community-release-el9.rpm; [ -n "$2" ] && CONFIG_PACKAGE_NAME=$2 +MYSQL_CLIENT_PACKAGE_NAME=mysql-community-client; [ -n "$3" ] && MYSQL_CLIENT_PACKAGE_NAME=$3 +MYSQL_ROUTER_PACKAGE_NAME=mysql-router-community; [ -n "$4" ] && MYSQL_ROUTER_PACKAGE_NAME=$4 +MYSQL_CLIENT_VERSION=mysql-community-client; [ -n "$5" ] && MYSQL_CLIENT_VERSION=$5 +MYSQL_ROUTER_VERSION=mysql-router-community; [ -n "$6" ] && MYSQL_ROUTER_VERSION=$6 +REPO_NAME_SERVER=mysql80-community; [ -n "$7" ] && REPO_NAME_SERVER=$7 +REPO_NAME_TOOLS=mysql-tools-community; [ -n "$8" ] && REPO_NAME_TOOLS=$8 + +MAJOR_VERSION=$(echo $MYSQL_CLIENT_VERSION | cut -d'.' -f'1,2') + +MYSQL_CLIENT_PACKAGE=$MYSQL_CLIENT_PACKAGE_NAME-$MYSQL_CLIENT_VERSION +MYSQL_ROUTER_PACKAGE=$MYSQL_ROUTER_PACKAGE_NAME-$MYSQL_ROUTER_VERSION + +echo "In the place" +echo `ls` +if [ ! -d "${MAJOR_VERSION}" ]; then + mkdir -p "${MAJOR_VERSION}/inspec" +fi + +sed 's#%%MYSQL_CLIENT_PACKAGE%%#'"${MYSQL_CLIENT_PACKAGE}"'#g' template/Dockerfile > tmpFile +sed -i 's#%%MYSQL_ROUTER_PACKAGE%%#'"${MYSQL_ROUTER_PACKAGE}"'#g' tmpFile +sed -i 's#%%CONFIG_PACKAGE_NAME%%#'"${CONFIG_PACKAGE_NAME}"'#g' tmpFile +sed -i 's#%%REPO%%#'"${REPO}"'#g' tmpFile +sed -i 's#%%REPO_NAME_SERVER%%#'"${REPO_NAME_SERVER}"'#g' tmpFile +sed -i 's#%%REPO_NAME_TOOLS%%#'"${REPO_NAME_TOOLS}"'#g' tmpFile +mv tmpFile ${MAJOR_VERSION}/Dockerfile + +# update test template +sed -e 's#%%MYSQL_CLIENT_PACKAGE_NAME%%#'"${MYSQL_CLIENT_PACKAGE_NAME}"'#g' template/control.rb > tmpFile +sed -i -e 's#%%MYSQL_CLIENT_VERSION%%#'"${MYSQL_CLIENT_VERSION}"'#g' tmpFile +sed -i -e 's#%%MYSQL_ROUTER_PACKAGE_NAME%%#'"${MYSQL_ROUTER_PACKAGE_NAME}"'#g' tmpFile +sed -i -e 's#%%MYSQL_ROUTER_VERSION%%#'"${MYSQL_ROUTER_VERSION}"'#g' tmpFile +sed -i -e 's#%%MAJOR_VERSION%%#'"${MAJOR_VERSION}"'#g' tmpFile +mv tmpFile "${MAJOR_VERSION}/inspec/control.rb" + +# copy entrypoint script +cp template/run.sh ${MAJOR_VERSION}/run.sh +chmod +x ${MAJOR_VERSION}/run.sh + +cp README.md ${MAJOR_VERSION}/ diff --git a/mysql-router/manifest.sh b/mysql-router/manifest.sh new file mode 100755 index 000000000..a0415dac7 --- /dev/null +++ b/mysql-router/manifest.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright (c) 2018, 2023 Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e +source ./VERSION + +if grep -q Microsoft /proc/version; then + echo "Running on Windows Subsystem for Linux" + # WSL doesn't have its own docker host, we have to use the one + # from Windows itself. + # https://medium.com/@sebagomez/installing-the-docker-client-on-ubuntus-windows-subsystem-for-linux-612b392a44c4 + export DOCKER_HOST=localhost:2375 +fi + +REPO=mysql/mysql-router; [ -n "$1" ] && REPO=$1 +MAJOR_VERSIONS=("${!MYSQL_SERVER_VERSIONS[@]}"); [ -n "$2" ] && MAJOR_VERSIONS=("${@:2}") + +WEEKLY=0 + +if [[ "$REPO" =~ (weekly) ]]; then + WEEKLY=1 +fi + +MANIFEST_VERSIONS=$(./tag.sh "" "$WEEKLY" "${MAJOR_VERSIONS[@]}") +for MANIFEST_VERSION in $MANIFEST_VERSIONS; do + docker pull "$REPO:$MANIFEST_VERSION-arm64" "$REPO:$MANIFEST_VERSION-amd64" + docker manifest create "$REPO:$MANIFEST_VERSION" "$REPO:$MANIFEST_VERSION-arm64" "$REPO:$MANIFEST_VERSION-amd64" + docker manifest add "$REPO:$MANIFEST_VERSION" "$REPO:$MANIFEST_VERSION-arm64" --os linux --arch arm64 + docker manifest add "$REPO:$MANIFEST_VERSION" "$REPO:$MANIFEST_VERSION-amd64" --os linux --arch amd64 + docker manifest push "$REPO:$MANIFEST_VERSION" "docker://$REPO:$MANIFEST_VERSION" +done diff --git a/mysql-router/tag.sh b/mysql-router/tag.sh new file mode 100755 index 000000000..5e35f7527 --- /dev/null +++ b/mysql-router/tag.sh @@ -0,0 +1,24 @@ +#!/bin/bash +# Copyright (c) 2021, 2023 Oracle and/or its affiliates. +# +set -e +source VERSION + +SUFFIX='' [ -n "$1" ] && SUFFIX=$1 +WEEKLY='' [ -n "$2" ] && WEEKLY=$2 +MAJOR_VERSIONS=("${!MYSQL_ROUTER_VERSIONS[@]}"); [ -n "$3" ] && MAJOR_VERSIONS=("${@:3}") + +for MAJOR_VERSION in "${MAJOR_VERSIONS[@]}"; do + if [ "$WEEKLY" == "1" ]; then + ROUTER_VERSION=${WEEKLY_ROUTER_VERSIONS["${MAJOR_VERSION}"]} + else + ROUTER_VERSION=${MYSQL_ROUTER_VERSIONS["${MAJOR_VERSION}"]} + fi + FULL_ROUTER_VERSION="${ROUTER_VERSION}-${IMAGE_VERSION}" + MAJOR_VERSION=${ROUTER_VERSION%.*} + TAGS="${MAJOR_VERSION}${SUFFIX} ${ROUTER_VERSION}${SUFFIX} ${FULL_ROUTER_VERSION}${SUFFIX}" + if [[ "$MAJOR_VERSION" == "$LATEST" ]]; then + TAGS="$TAGS latest${SUFFIX}" + fi + echo $TAGS +done diff --git a/mysql-router/template/Dockerfile b/mysql-router/template/Dockerfile new file mode 100644 index 000000000..0f9990893 --- /dev/null +++ b/mysql-router/template/Dockerfile @@ -0,0 +1,39 @@ +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_CLIENT_PACKAGE=%%MYSQL_CLIENT_PACKAGE%% +ARG MYSQL_ROUTER_PACKAGE=%%MYSQL_ROUTER_PACKAGE%% +ARG CONFIG_PACKAGE_NAME=%%CONFIG_PACKAGE_NAME%% +ARG REPO_NAME_SERVER=%%REPO_NAME_SERVER%% +ARG REPO_NAME_TOOLS=%%REPO_NAME_TOOLS%% + +RUN /usr/sbin/groupadd -g 999 -r mysqlrouter >/dev/null \ + && /usr/sbin/useradd -M -N -u 999 -g mysqlrouter -r -d /var/lib/mysqlrouter -s /bin/false \ + -c "MySQL Router" mysqlrouter \ + && rpm -U %%REPO%%/$CONFIG_PACKAGE_NAME \ + && microdnf install -y \ + --enablerepo=%%REPO_NAME_SERVER%% $MYSQL_CLIENT_PACKAGE \ + && microdnf install -y --disablerepo=\* \ + --enablerepo=%%REPO_NAME_TOOLS%% $MYSQL_ROUTER_PACKAGE \ + && microdnf clean all + +COPY run.sh /run.sh +HEALTHCHECK \ + CMD mysqladmin --port 6446 --protocol TCP ping 2>&1 | grep Access || exit 1 +EXPOSE 6446 6447 6448 6449 6450 8443 +USER 999:999 +ENTRYPOINT ["/run.sh"] +CMD ["mysqlrouter"] diff --git a/mysql-router/template/control.rb b/mysql-router/template/control.rb new file mode 100644 index 000000000..5491164a4 --- /dev/null +++ b/mysql-router/template/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /sleep/ } + its('images') { should cmp /mysql-router:%%MAJOR_VERSION%%/ } + its('names') { should include "mysql-router-%%MAJOR_VERSION%%" } + end +end +control 'packages' do + impact 0.5 + describe package('%%MYSQL_CLIENT_PACKAGE_NAME%%') do + it { should be_installed } + its ('version') { should match '%%MYSQL_CLIENT_VERSION%%.*' } + end + describe package('%%MYSQL_ROUTER_PACKAGE_NAME%%') do + it { should be_installed } + its ('version') { should match '%%MYSQL_ROUTER_VERSION%%.*' } + end +end diff --git a/mysql-router/template/run.sh b/mysql-router/template/run.sh new file mode 100755 index 000000000..79bb35080 --- /dev/null +++ b/mysql-router/template/run.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# Copyright (c) 2018, 2024, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +if [[ -n $MYSQL_USER_FILE && -f $MYSQL_USER_FILE ]]; then + MYSQL_USER=$(cat $MYSQL_USER_FILE) +fi + +if [ "$1" = 'mysqlrouter' ]; then + if [[ -z $MYSQL_HOST || -z $MYSQL_PORT || -z $MYSQL_USER || (-z $MYSQL_PASSWORD && -z $MYSQL_PASSWORD_FILE) ]]; then + echo "We require all of" + echo " MYSQL_HOST" + echo " MYSQL_PORT" + echo " MYSQL_USER or MYSQL_USER_FILE" + echo " MYSQL_PASSWORD or MYSQL_PASSWORD_FILE" + echo "to be set." + echo "In addition you can set" + echo " MYSQL_INNODB_CLUSTER_MEMBERS" + echo " MYSQL_CREATE_ROUTER_USER" + echo " MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS" + echo "Exiting." + exit 1 + fi + + PASSFILE=$(mktemp) + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" > "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" > "$PASSFILE" + fi + if [ -z $MYSQL_CREATE_ROUTER_USER ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + MYSQL_CREATE_ROUTER_USER=1 + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not set, Router will generate a new account to be used at runtime." + echo "[Entrypoint] Set it to 0 to reuse $MYSQL_USER instead." + elif [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + cat "$MYSQL_PASSWORD_FILE" >> "$PASSFILE" + echo "" >> "$PASSFILE" + else + echo "$MYSQL_PASSWORD" >> "$PASSFILE" + fi + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is 0, Router will reuse $MYSQL_USER account at runtime" + else + echo "[Entrypoint] MYSQL_CREATE_ROUTER_USER is not 0, Router will generate a new account to be used at runtime" + fi + + if [[ -n $MYSQL_PASSWORD_FILE && -f "$MYSQL_PASSWORD_FILE" ]]; then + DEFAULTS_EXTRA_FILE=$(mktemp) + cat >"$DEFAULTS_EXTRA_FILE" <"$DEFAULTS_EXTRA_FILE" < "/dev/tcp/$MYSQL_HOST/$MYSQL_PORT") >/dev/null 2>&1; do + echo "[Entrypoint] Waiting for mysql server $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST:$MYSQL_PORT. Checking for cluster state." + if ! [[ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -e "show status;" 2> /dev/null)" ]]; then + echo "[Entrypoint] ERROR: Can not connect to database. Exiting." + exit 1 + fi + if [[ -n $MYSQL_INNODB_CLUSTER_MEMBERS ]]; then + attempt_num=0 + echo $attempt_num + echo $max_tries + until [ "$(mysql --defaults-extra-file="$DEFAULTS_EXTRA_FILE" -u "$MYSQL_USER" -h "$MYSQL_HOST" -P "$MYSQL_PORT" -N performance_schema -e "select count(MEMBER_STATE) >= $MYSQL_INNODB_CLUSTER_MEMBERS from replication_group_members where MEMBER_STATE = 'ONLINE';" 2> /dev/null)" -eq 1 ]; do + echo "[Entrypoint] Waiting for $MYSQL_INNODB_CLUSTER_MEMBERS cluster instances to become available via $MYSQL_HOST ($attempt_num/$max_tries)" + sleep $(( attempt_num++ )) + if (( attempt_num == max_tries )); then + exit 1 + fi + done + echo "[Entrypoint] Successfully contacted cluster with $MYSQL_INNODB_CLUSTER_MEMBERS members. Bootstrapping." + fi + if [ $(id -u) = "0" ]; then + opt_user=--user=mysqlrouter + fi + if [ "$MYSQL_CREATE_ROUTER_USER" = "0" ]; then + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap reusing account \"$MYSQL_USER\"." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force --account-create=never --account=$MYSQL_USER $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + else + echo "[Entrypoint] Succesfully contacted mysql server at $MYSQL_HOST. Trying to bootstrap." + mysqlrouter --bootstrap "$MYSQL_USER@$MYSQL_HOST:$MYSQL_PORT" --directory /tmp/mysqlrouter --force $opt_user $MYSQL_ROUTER_BOOTSTRAP_EXTRA_OPTIONS < "$PASSFILE" || exit 1 + fi + + rm "$DEFAULTS_EXTRA_FILE" + + sed -i -e 's/logging_folder=.*$/logging_folder=/' /tmp/mysqlrouter/mysqlrouter.conf + echo "[Entrypoint] Starting mysql-router." + exec "$@" --config /tmp/mysqlrouter/mysqlrouter.conf + + rm $PASSFILE +else + exec "$@" +fi diff --git a/mysql-router/test.sh b/mysql-router/test.sh new file mode 100755 index 000000000..1dc8e1cdf --- /dev/null +++ b/mysql-router/test.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright (c) 2018, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# This script will simply use sed to replace placeholder variables in the +# files in template/ with version-specific variants. + +set -e +source ./VERSION + +ARCH=amd64; [ -n "$1" ] && ARCH=$1 +WEEKLY=''; [ -n "$2" ] && WEEKLY=$2 +MAJOR_VERSIONS=("${!MYSQL_ROUTER_VERSIONS[@]}"); [ -n "$3" ] && MAJOR_VERSIONS=("${@:3}") + +for MAJOR_VERSION in "${MAJOR_VERSIONS[@]}"; do + if [ "$WEEKLY" == "1" ]; then + ROUTER_VERSION=${WEEKLY_ROUTER_VERSIONS["${MAJOR_VERSION}"]} + else + ROUTER_VERSION=${MYSQL_ROUTER_VERSIONS["${MAJOR_VERSION}"]} + fi + MAJOR_VERSION=${ROUTER_VERSION%.*} + podman run -d --rm -e MYSQL_HOST=x -e MYSQL_PORT=9 -e MYSQL_USER=x -e MYSQL_PASSWORD=x -e MYSQL_INNODB_CLUSTER_MEMBERS=1 --name "mysql-router-$MAJOR_VERSION" mysql/mysql-router:$MAJOR_VERSION-$ARCH sleep 5000 + export DOCKER_HOST=unix:///tmp/podman.sock + podman system service --time=0 ${DOCKER_HOST} & DOCKER_SOCK_PID="$!" + inspec exec $MAJOR_VERSION/inspec/control.rb --controls container + inspec exec $MAJOR_VERSION/inspec/control.rb -t "docker://mysql-router-$MAJOR_VERSION" --controls packages + podman stop -i "mysql-router-$MAJOR_VERSION" + podman rm -i -f "mysql-router-$MAJOR_VERSION" + kill -TERM ${DOCKER_SOCK_PID} + rm -f /tmp/podman.sock +done diff --git a/mysql-server/8.0/Dockerfile b/mysql-server/8.0/Dockerfile new file mode 100644 index 000000000..d135ff3d2 --- /dev/null +++ b/mysql-server/8.0/Dockerfile @@ -0,0 +1,45 @@ +# Copyright (c) 2017, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +FROM container-registry.oracle.com/os/oraclelinux:9-slim + +ARG MYSQL_SERVER_PACKAGE=mysql-community-server-minimal-8.0.44 +ARG MYSQL_SHELL_PACKAGE=mysql-shell-8.0.44 + +# Setup repositories for minimal packages (all versions) +RUN rpm -U https://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/mysql-community-minimal-release-el9.rpm \ + && rpm -U https://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/mysql84-community-release-el9.rpm + +# Install server and shell 8.0 +RUN microdnf update && echo "[main]" > /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql80-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove -y mysql-community-minimal-release mysql84-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/8.0/docker-entrypoint.sh b/mysql-server/8.0/docker-entrypoint.sh new file mode 100755 index 000000000..1e759568d --- /dev/null +++ b/mysql-server/8.0/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 8.0.44-1.2.23-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --user=$MYSQLD_USER --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol8_appstream \ + --enablerepo=mysql-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove mysql-community-minimal-release mysql80-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/8.1/docker-entrypoint.sh b/mysql-server/8.1/docker-entrypoint.sh new file mode 100755 index 000000000..5ad9acb38 --- /dev/null +++ b/mysql-server/8.1/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 8.1.0-1.2.13-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol8_appstream \ + --enablerepo=mysql-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove mysql-community-minimal-release mysql80-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/8.2/docker-entrypoint.sh b/mysql-server/8.2/docker-entrypoint.sh new file mode 100755 index 000000000..0de06ba24 --- /dev/null +++ b/mysql-server/8.2/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 8.2.0-1.2.14-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol8_appstream \ + --enablerepo=mysql-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove mysql-community-minimal-release mysql80-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/8.3/docker-entrypoint.sh b/mysql-server/8.3/docker-entrypoint.sh new file mode 100755 index 000000000..1111b900e --- /dev/null +++ b/mysql-server/8.3/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 8.3.0-1.2.15-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-8.4-lts-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-8.4-lts-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove -y mysql-community-minimal-release mysql84-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/8.4/docker-entrypoint.sh b/mysql-server/8.4/docker-entrypoint.sh new file mode 100755 index 000000000..2e7bcf1d9 --- /dev/null +++ b/mysql-server/8.4/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 8.4.7-1.2.23-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --user=$MYSQLD_USER --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove -y mysql-community-minimal-release mysql84-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/9.0/docker-entrypoint.sh b/mysql-server/9.0/docker-entrypoint.sh new file mode 100755 index 000000000..94029c497 --- /dev/null +++ b/mysql-server/9.0/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 9.0.1-1.2.18-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove -y mysql-community-minimal-release mysql84-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/9.1/docker-entrypoint.sh b/mysql-server/9.1/docker-entrypoint.sh new file mode 100755 index 000000000..17ff28ef6 --- /dev/null +++ b/mysql-server/9.1/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 9.1.0-1.2.19-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove -y mysql-community-minimal-release mysql84-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/9.2/docker-entrypoint.sh b/mysql-server/9.2/docker-entrypoint.sh new file mode 100755 index 000000000..dc7c81e99 --- /dev/null +++ b/mysql-server/9.2/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 9.2.0-1.2.20-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove -y mysql-community-minimal-release mysql84-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/9.3/docker-entrypoint.sh b/mysql-server/9.3/docker-entrypoint.sh new file mode 100755 index 000000000..856f30060 --- /dev/null +++ b/mysql-server/9.3/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 9.3.0-1.2.21-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove -y mysql-community-minimal-release mysql84-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/9.4/docker-entrypoint.sh b/mysql-server/9.4/docker-entrypoint.sh new file mode 100755 index 000000000..482605bea --- /dev/null +++ b/mysql-server/9.4/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 9.4.0-1.2.22-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --user=$MYSQLD_USER --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-innovation-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=mysql-innovation-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove -y mysql-community-minimal-release mysql84-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/9.5/docker-entrypoint.sh b/mysql-server/9.5/docker-entrypoint.sh new file mode 100755 index 000000000..f0a9abec4 --- /dev/null +++ b/mysql-server/9.5/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image 9.5.0-1.2.23-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --user=$MYSQLD_USER --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" <. + +Supported Tags and Respective Dockerfile Links +---------------------------------------------- + +> **Warning** +> +> The MySQL Docker images maintained by the MySQL team are built specifically for Linux platforms. Other platforms are not supported, and users using these MySQL Docker images on them are doing so at their own risk. See [the discussion here](https://dev.mysql.com/doc/refman/8.0/en/deploy-mysql-nonlinux-docker.html) for some known limitations for running these containers on non-Linux operating systems. + +These are tags for some of the optimized MySQL Server Docker images, created and maintained by the MySQL team at Oracle (for a full list, see [the Tags tab of this page](https://hub.docker.com/r/mysql/mysql-server/tags/)). [DS] The tags are updated directly on the posted Markdown versions by RE after eahc release, so it might remain outdated in this DocBook source file. + +- MySQL Server 5.7 (tag: [`5.7`, `5.7.24`, `5.7.24-1.1.8`](https://github.com/mysql/mysql-docker/mysql-server/5.7/Dockerfile)) ([mysql-server/5.7/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-server/5.7/Dockerfile)) + +- MySQL Server 8.0, the latest GA (tag: [`8.0`, `8.0.23`, `8.0.23-1.2.0`, `latest`](https://github.com/mysql/mysql-docker/mysql-server/8.0/Dockerfile)) ([mysql-server/8.0/Dockerfile](https://github.com/mysql/mysql-docker/blob/mysql-server/8.0/Dockerfile)) + +- MySQL Server 8.0 is also available for AArch64 (ARM64), using the same tags. + +Images are updated when new MySQL Server maintenance releases and development milestones are published. Please note that any non-GA releases are for preview purposes only and should not be used in production setups. + +We also from time to time publish special MySQL Server images that contain experimental features. + +Quick Reference +--------------- + +- *Detailed documentation:* See [Deploying MySQL on Linux with Docker](https://dev.mysql.com/doc/refman/8.0/en/linux-installation-docker.html) in the [MySQL Reference Manual](https://dev.mysql.com/doc/refman/8.0/en/). + +- *Where to file issues:* Please submit a bug report at under the category “MySQL Package Repos and Docker Images”. + +- *Maintained by:* The MySQL team at Oracle + +- *Source of this image:* The [Image repository for the `mysql/mysql-server` container](https://github.com/mysql/mysql-docker) + +- *Supported Docker versions:* The latest stable release is supported. Support for older versions (down to 1.0) is provided on a best-effort basis, but we strongly recommend using the most recent stable Docker version, which this documentation assumes. + +How to Use the MySQL Images +--------------------------- + +### Downloading a MySQL Server Docker Image + +Downloading the server image in a separate step is not strictly necessary; however, performing this before you create your Docker container ensures your local image is up to date. + +To download the MySQL Community Edition image, run this command: + + shell> docker pull mysql/mysql-server:tag +  +Refer to the list of supported tags above. If `:tag + ` is omitted, the `latest` tag is used, and the image for the latest GA version of MySQL Server is downloaded. + +### Starting a MySQL Server Instance + +Start a new Docker container for the MySQL Community Server with this command: + + shell> docker run --name=mysql1 -d mysql/mysql-server:tag +  +The `--name` option, for supplying a custom name for your server container (`mysql1` in the example), is optional; if no container name is supplied, a random one is generated. If the Docker image of the specified name and tag has not been downloaded by an earlier `docker pull` or `docker run` command, the image is now downloaded. After download completes, initialization for the container begins, and the container appears in the list of running containers when you run the `docker ps` command; for example: + + shell> docker ps + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + a24888f0d6f4 mysql/mysql-server "/entrypoint.sh my..." 14 seconds ago Up 13 seconds (health: starting) 3306/tcp, 33060/tcp mysql1 +  +The container initialization might take some time. When the server is ready for use, the `STATUS` of the container in the output of the `docker ps` command changes from `(health: starting)` to `(healthy)`. + +The `-d` option used in the `docker + run` command above makes the container run in the background. Use this command to monitor the output from the container: + + shell> docker logs mysql1 +  +Once initialization is finished, the command's output is going to contain the random password generated for the root user; check the password with, for example, this command: + + shell> docker logs mysql1 2>&1 | grep GENERATED + GENERATED ROOT PASSWORD: Axegh3kAJyDLaRuBemecis&EShOs +  +### Connecting to MySQL Server from within the Container + +Once the server is ready, you can run the `mysql` client within the MySQL Server container you just started and connect it to the MySQL Server. Use the `docker exec -it` command to start a `mysql` client inside the Docker container you have started, like this: + + shell> docker exec -it mysql1 mysql -uroot -p +  +When asked, enter the generated root password (see the instructions above on how to find it). Because the `MYSQL_ONETIME_PASSWORD` option is true by default, after you have connected a `mysql` client to the server, you must reset the server root password by issuing this statement: + + mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'password'; +  +Substitute `password` with the password of your choice. Once the password is reset, the server is ready for use. + +### Products Included in the Container + +A number of MySQL products are included in the Docker container you created with the MySQL Server Docker image: + +- MySQL Server and other MySQL Programs including the [mysql](https://dev.mysql.com/doc/refman/8.0/en/mysql.html) client,[mysqladmin](https://dev.mysql.com/doc/refman/8.0/en/mysqladmin.html), [mysqldump](https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html), and so on. See the [MySQL Reference Manual](https://dev.mysql.com/doc/refman/8.0/en/programs-overview.html) for documentation of the products. + +- MySQL Shell. See the [MySQL Shell User Guide](https://dev.mysql.com/doc/refman/8.0/en/mysql-shell.html) for documentation of the product. + +### More Topics on Deploying MySQL Server with Docker + +For more topics on deploying MySQL Server with Docker like starting and connecting to the server, server configuration, persisting data and configuration, server error log, server upgrades, and the Docker environment variables, see [Deploying MySQL Server with Docker](https://dev.mysql.com/doc/refman/8.0/en/linux-installation-docker.html) in the MySQL Server manual. diff --git a/mysql-server/VERSION b/mysql-server/VERSION new file mode 100644 index 000000000..56e620e18 --- /dev/null +++ b/mysql-server/VERSION @@ -0,0 +1,43 @@ +IMAGE_VERSION=1.2.23-server + +# LATEST is always set to the +# current highest release, which is, +# either 'innovation' or an LTS series +# i.e. 9.7, or 10.7 + +LATEST="innovation" + + + +# LATEST_LTS is set to the highest +# LTS series currently being released +# i.e. when 9.7 release will come it +# will be set to 9.7 up till 10.7 and +# then 10.7 and so on + +LATEST_LTS="8.4" + + + +# The value of key should be series +# i.e. 8.0, 8.4, innovation, 9.7, etc. +# do not use any other value for key +# like 'latest-8.4' or 'lts-84', etc. + +declare -A MYSQL_SERVER_VERSIONS WEEKLY_SERVER_VERSIONS +MYSQL_SERVER_VERSIONS["8.0"]=8.0.44 +MYSQL_SERVER_VERSIONS["8.4"]=8.4.7 +MYSQL_SERVER_VERSIONS["innovation"]=9.5.0 + +WEEKLY_SERVER_VERSIONS["8.0"]=8.0.44 +WEEKLY_SERVER_VERSIONS["8.4"]=8.4.7 +WEEKLY_SERVER_VERSIONS["innovation"]=9.5.0 + +declare -A MYSQL_SHELL_VERSIONS WEEKLY_SHELL_VERSIONS +MYSQL_SHELL_VERSIONS["8.0"]=8.0.44 +MYSQL_SHELL_VERSIONS["8.4"]=8.4.7 +MYSQL_SHELL_VERSIONS["innovation"]=9.5.0 + +WEEKLY_SHELL_VERSIONS["8.0"]=8.0.44 +WEEKLY_SHELL_VERSIONS["8.4"]=8.4.7 +WEEKLY_SHELL_VERSIONS["innovation"]=9.5.0 diff --git a/mysql-server/build.sh b/mysql-server/build.sh new file mode 100755 index 000000000..3212e2b7e --- /dev/null +++ b/mysql-server/build.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright (c) 2018, 2023 Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e +source ./VERSION + +if grep -q Microsoft /proc/version; then + echo "Running on Windows Subsystem for Linux" + # WSL doesn't have its own docker host, we have to use the one + # from Windows itself. + # https://medium.com/@sebagomez/installing-the-docker-client-on-ubuntus-windows-subsystem-for-linux-612b392a44c4 + export DOCKER_HOST=localhost:2375 +fi + +ARCH=amd64; [ -n "$1" ] && ARCH=$1 +BUILD_TYPE=community; [ -n "$2" ] && BUILD_TYPE=$2 +MAJOR_VERSIONS=("${!MYSQL_SERVER_VERSIONS[@]}"); [ -n "$3" ] && MAJOR_VERSIONS=("${@:3}") + +if [[ ${BUILD_TYPE} =~ (commercial) ]]; then + IMG_LOC=store/oracle/mysql-enterprise-server +else + IMG_LOC=mysql/mysql-server +fi + +for MAJOR_VERSION in "${MAJOR_VERSIONS[@]}"; do + if [[ "$BUILD_TYPE" =~ (weekly) ]]; then + SERVER_VERSION=${WEEKLY_SERVER_VERSIONS["${MAJOR_VERSION}"]} + else + SERVER_VERSION=${MYSQL_SERVER_VERSIONS["${MAJOR_VERSION}"]} + fi + MAJOR_VERSION=${SERVER_VERSION%.*} + docker build --build-arg http_proxy="$http_proxy" --build-arg https_proxy="$http_proxy" --build-arg no_proxy="$no_proxy" -t $IMG_LOC:"$MAJOR_VERSION"-$ARCH "$MAJOR_VERSION" +done diff --git a/mysql-server/changelog b/mysql-server/changelog new file mode 100644 index 000000000..eb8b16e60 --- /dev/null +++ b/mysql-server/changelog @@ -0,0 +1,75 @@ +Changes in 1.2.0 (2021-01-15) + * Removed EOLed 5.5 and 5.6 + * Upgraded base image to el8-slim, switched from yum to microdnf + * Generate password internally in entryfile, removed pwmake + * Support for running in a container as non-root/mysql user + * Write MySQL files in /var/lib/mysql instead of / + * Always log to stderr + * Added MYSQL_INITIALIZE_ONLY option + +Changes in 1.1.5 (2018-04-19) + * Bumped server versions to 5.5.60, 5.6.40, 5.7.22 + * MySQL Server 8.0 updated to 8.0.11 + * Bumped Shell 8.0 version to 8.0.11 + +Changes in 1.1.4 (2018-01-24) + * MySQL Server 8.0 updated to 8.0.4-rc + +Changes in 1.1.3 (2018-01-15) + * Bumped server versions to 5.5.59, 5.6.39, 5.7.21 + * Bumped Shell 1.0 version to 1.0.11 + +Changes in 1.1.2 (2017-10-16) + * Bumped server versions to 5.5.58, 5.6.38, 5.7.20 + * Bumped Shell 8.0 version to 8.0.3 + +Changes in 1.1.1 (2017-09-22) + * Disable binlog for all entrypoint client commands (#87305) + This was previously only done only for the script to set the root password, + but should be done for all client commands, or group replication will fail + * Add flag for logging to console (#87458) + Setting -e MYSQL_LOG_CONSOLE=true will make the server log to console, so the + server log is available through Docker's log interface. If /etc/my.cnf is + mounted from the host system, this has no effect. On 8.0, this is the default + behavior. + * Ensure both MYSQL_USER and MYSQL_PASSWORD are set (#86982) + Before, setting only one would cause the option to be silently ignored. + * Read password file first and throw error if it is empty (#87025) + Setting MYSQL_ROOT_PASSWORD to an empty string would be rejected, but + setting it to a file with no content would be accepted. Both are now rejected. + * MYSQL_RANDOM_ROOT_PASSWORD and MYSQL_ONETIME_PASSWORD are now set by default. (#87515) + A password option no longer needs to be set explicitly. If none are set, a + random, expired password is set. + * Make root@$MYSQL_ROOT_HOST identical to root@localhost (#86945) + If the MYSQL_ROOT_HOST variable is set we add an additional root user for + the given host. This user was missing the PROXY privilege. We add the + missing privilege so the users are identical. + * MySQL Server 8.0 updated to 8.0.3-rc + * MySQL Shell for 5.7 updated to 1.0.10 + +Changes in 1.1.0 (2017-07-24) + * Fixed broken MYSQL_ONETIME_PASSWORD support (#86523) + The functionality wasn't correctly updated when the entrypoint script was + changed to only create the root@localhost user by default + * Changed control files to be generated from a common template + The control files for each version will be generated by swapping out the few + commands that differ between server versions + * Made PACKAGE_URL an ARG entry, to allow build-time changing + The URL variables can be changed by supplying new ones with --build-arg at + build time + * Added basic healthcheck script + Once database init is complete a flag file will be touched. If this file + exists and mysqladmin ping succeeds, the container is reported as healthy, + meaning it is ready for use + * Database init will now use configured socket setting instead of hardcoded + Using a hardcoded socket could cause init scripts to fail in confusing ways + if the user customized the socket setting + * Added MySQL Shell to supported images + For 5.7 and 8.0, MySQL Shell is installed together with the server. + https://dev.mysql.com/doc/refman/5.7/en/mysql-shell.html + +Known issues: + * For existing databases created with older images/not with Docker, the + healthcheck script will generate an "Access denied for healthchecker@localhost" + message in the server log every time it runs. If connection throttling is + enabled this could eventually cause the healthcheck to fail diff --git a/mysql-server/gen_dockerfiles.sh b/mysql-server/gen_dockerfiles.sh new file mode 100755 index 000000000..2f55e9b9f --- /dev/null +++ b/mysql-server/gen_dockerfiles.sh @@ -0,0 +1,115 @@ +#!/bin/bash +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e +# This script will simply use sed to replace placeholder variables in the +# files in template/ with version-specific variants. + +source ./VERSION + +REPO=https://repo.mysql.com; [ -n "$1" ] && REPO=$1 +CONFIG_PACKAGE_NAME=mysql80-community-release-el9.rpm; [ -n "$2" ] && CONFIG_PACKAGE_NAME=$2 +CONFIG_PACKAGE_NAME_MINIMAL=mysql-community-minimal-release-el9.rpm; [ -n "$3" ] && CONFIG_PACKAGE_NAME_MINIMAL=$3 + +REPO_NAME_SERVER=mysql80-community-minimal; [ -n "$4" ] && REPO_NAME_SERVER=$4 +REPO_NAME_TOOLS=mysql-tools-community; [ -n "$5" ] && REPO_NAME_TOOLS=$5 + +MYSQL_SERVER_PACKAGE_NAME="mysql-community-server-minimal"; [ -n "$6" ] && MYSQL_SERVER_PACKAGE_NAME=$6 +MYSQL_SHELL_PACKAGE_NAME="mysql-shell"; [ -n "$7" ] && MYSQL_SHELL_PACKAGE_NAME=$7 +MYSQL_VERSION=""; [ -n "$8" ] && MYSQL_VERSION=$8 +SHELL_VERSION=""; [ -n "$9" ] && SHELL_VERSION=$9 +MYSQL_CONFIG_PKG_MINIMAL="mysql-community-minimal-release"; [ -n "${10}" ] && MYSQL_CONFIG_PKG_MINIMAL=${10} +MYSQL_CONFIG_PKG="mysql80-community-release"; [ -n "${11}" ] && MYSQL_CONFIG_PKG=${11} + +# Get the Major Version +MAJOR_VERSION=${MYSQL_VERSION%.*} + +if [[ ${MYSQL_CONFIG_PKG_MINIMAL} =~ (community) ]]; then + CONT_NAME="mysql-server" +else + CONT_NAME="mysql-enterprise-server" +fi + +# 33060 is the default port for the mysqlx plugin, new to 5.7 +declare -A PORTS +# MySQL 8.0 supports a call to validate the config, while older versions have it as a side +# effect of running --verbose --help +declare -A VALIDATE_CONFIG +# Data directories that must be created with special ownership and permissions when the image is built +declare -A PRECREATE_DIRS +PRECREATE_DIRS="/var/lib/mysql /var/lib/mysql-files /var/lib/mysql-keyring /var/run/mysqld" + +declare -A DOCKERFILE_TEMPLATES + +declare -A PASSWORDSET +PASSWORDSET="ALTER USER 'root'@'localhost' IDENTIFIED BY '\${MYSQL_ROOT_PASSWORD}';" + +declare -A SPEC_PORTS + + +PORTS="3306 33060 33061" +VALIDATE_CONFIG="output=\$(\"\$@\" --user=\$MYSQLD_USER --validate-config) || result=\$?" +DOCKERFILE_TEMPLATES="template/Dockerfile" +SPEC_PORTS="3306/tcp, 33060-33061/tcp" + +if [ ! -d "${MAJOR_VERSION}" ]; then + mkdir -p "${MAJOR_VERSION}/inspec" +fi + +MYSQL_SERVER_PACKAGE=${MYSQL_SERVER_PACKAGE_NAME}-${MYSQL_VERSION} +MYSQL_SHELL_PACKAGE=${MYSQL_SHELL_PACKAGE_NAME}-${SHELL_VERSION} + +# Dockerfiles +sed 's#%%MYSQL_SERVER_PACKAGE%%#'"${MYSQL_SERVER_PACKAGE}"'#g' ${DOCKERFILE_TEMPLATES} > tmpfile +sed -i 's#%%REPO%%#'"${REPO}"'#g' tmpfile +sed -i 's#%%CONFIG_PACKAGE_NAME%%#'"${CONFIG_PACKAGE_NAME}"'#g' tmpfile +sed -i 's#%%CONFIG_PACKAGE_NAME_MINIMAL%%#'"${CONFIG_PACKAGE_NAME_MINIMAL}"'#g' tmpfile +sed -i 's#%%REPO_NAME_SERVER%%#'"${REPO_NAME_SERVER}"'#g' tmpfile +sed -i 's#%%REPO_NAME_TOOLS%%#'"${REPO_NAME_TOOLS}"'#g' tmpfile + +sed -i 's#%%MYSQL_SHELL_PACKAGE%%#'"${MYSQL_SHELL_PACKAGE}"'#g' tmpfile + +sed -i 's#%%MYSQL_CONFIG_PKG_MINIMAL%%#'"${MYSQL_CONFIG_PKG_MINIMAL}"'#g' tmpfile +sed -i 's#%%MYSQL_CONFIG_PKG%%#'"${MYSQL_CONFIG_PKG}"'#g' tmpfile + +sed -i 's/%%PORTS%%/'"${PORTS}"'/g' tmpfile +mv tmpfile ${MAJOR_VERSION}/Dockerfile + +# Dockerfile_spec.rb +sed 's#%%MYSQL_SERVER_VERSION%%#'"${MYSQL_VERSION}"'#g' template/control.rb > tmpFile +sed -i 's#%%MYSQL_SHELL_VERSION%%#'"${SHELL_VERSION}"'#g' tmpFile +sed -i 's#%%MYSQL_SERVER_PACKAGE_NAME%%#'"${MYSQL_SERVER_PACKAGE_NAME}"'#g' tmpFile +sed -i 's#%%MYSQL_SHELL_PACKAGE_NAME%%#'"${MYSQL_SHELL_PACKAGE_NAME}"'#g' tmpFile +sed -i 's#%%MAJOR_VERSION%%#'"${MAJOR_VERSION}"'#g' tmpFile +sed -i 's#%%CONT_NAME%%#'"${CONT_NAME}"'#g' tmpFile +sed -i 's#%%PORTS%%#'"${SPEC_PORTS}"'#g' tmpFile +mv tmpFile "${MAJOR_VERSION}/inspec/control.rb" + +# Entrypoint +FULL_SERVER_VERSION="$MYSQL_VERSION-${IMAGE_VERSION}" +sed 's#%%PASSWORDSET%%#'"${PASSWORDSET}"'#g' template/docker-entrypoint.sh > tmpfile +sed -i 's#%%FULL_SERVER_VERSION%%#'"${FULL_SERVER_VERSION}"'#g' tmpfile +sed -i 's#%%VALIDATE_CONFIG%%#'"${VALIDATE_CONFIG}"'#g' tmpfile +mv tmpfile ${MAJOR_VERSION}/docker-entrypoint.sh +chmod +x ${MAJOR_VERSION}/docker-entrypoint.sh + +# Healthcheck +cp template/healthcheck.sh ${MAJOR_VERSION}/ +chmod +x ${MAJOR_VERSION}/healthcheck.sh + +# Build-time preparation script +sed 's#%%PRECREATE_DIRS%%#'"${PRECREATE_DIRS}"'#g' template/prepare-image.sh > tmpfile +mv tmpfile ${MAJOR_VERSION}/prepare-image.sh +chmod +x ${MAJOR_VERSION}/prepare-image.sh diff --git a/mysql-server/manifest.sh b/mysql-server/manifest.sh new file mode 100755 index 000000000..767c7632b --- /dev/null +++ b/mysql-server/manifest.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e +source ./VERSION + +if grep -q Microsoft /proc/version; then + echo "Running on Windows Subsystem for Linux" + # WSL doesn't have its own docker host, we have to use the one + # from Windows itself. + # https://medium.com/@sebagomez/installing-the-docker-client-on-ubuntus-windows-subsystem-for-linux-612b392a44c4 + export DOCKER_HOST=localhost:2375 +fi + +REPO=mysql/mysql-server; [ -n "$1" ] && REPO=$1 +MAJOR_VERSIONS=("${!MYSQL_SERVER_VERSIONS[@]}"); [ -n "$2" ] && MAJOR_VERSIONS=("${@:2}") + +WEEKLY=0 +if [[ "$REPO" =~ (weekly) ]]; then + WEEKLY=1 +fi + +MANIFEST_VERSIONS=$(./tag.sh "" "$WEEKLY" "${MAJOR_VERSIONS[@]}") +echo ${MANIFEST_VERSIONS} +for MANIFEST_VERSION in $MANIFEST_VERSIONS; do + docker pull "$REPO:$MANIFEST_VERSION-arm64" "$REPO:$MANIFEST_VERSION-amd64" + docker manifest create "$REPO:$MANIFEST_VERSION" "$REPO:$MANIFEST_VERSION-arm64" "$REPO:$MANIFEST_VERSION-amd64" + docker manifest add "$REPO:$MANIFEST_VERSION" "$REPO:$MANIFEST_VERSION-arm64" --os linux --arch arm64 + docker manifest add "$REPO:$MANIFEST_VERSION" "$REPO:$MANIFEST_VERSION-amd64" --os linux --arch amd64 + docker manifest push "$REPO:$MANIFEST_VERSION" "docker://$REPO:$MANIFEST_VERSION" +done diff --git a/mysql-server/mysql-community-minimal-release/Dockerfile b/mysql-server/mysql-community-minimal-release/Dockerfile new file mode 100644 index 000000000..be33e15f9 --- /dev/null +++ b/mysql-server/mysql-community-minimal-release/Dockerfile @@ -0,0 +1,45 @@ +# Copyright (c) 2017, 2023, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +FROM container-registry.oracle.com/os/oraclelinux:8-slim + +ARG MYSQL_SERVER_PACKAGE=mysql-community-server-minimal-mysql-community-minimal-release +ARG MYSQL_SHELL_PACKAGE=mysql-shell-mysql80-community-release + +# Setup repositories for minimal packages (all versions) +RUN rpm -U http://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/mysql-community-minimal-release-el8.rpm \ + && rpm -U http://repo.mysql.oraclecorp.com/mysql-uat/repos-stage/mysql80-community-release-el8.rpm + +# Install server and shell 8.0 +RUN microdnf update && echo "[main]" > /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=mysql-tools-community $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol8_appstream \ + --enablerepo=mysql5-community-minimal $MYSQL_SERVER_PACKAGE \ + && microdnf remove mysql-community-minimal-release mysql80-community-release \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE 3306 33060 33061 +CMD ["mysqld"] + diff --git a/mysql-server/mysql-community-minimal-release/docker-entrypoint.sh b/mysql-server/mysql-community-minimal-release/docker-entrypoint.sh new file mode 100755 index 000000000..9d640c962 --- /dev/null +++ b/mysql-server/mysql-community-minimal-release/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image mysql-community-minimal-release-1.2.14-server" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + output=$("$@" --validate-config) || result=$? + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}';" + else + ROOTCREATE="ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" < /etc/dnf/dnf.conf \ + && microdnf install -y --enablerepo=%%REPO_NAME_TOOLS%% $MYSQL_SHELL_PACKAGE \ + && microdnf install -y --disablerepo=ol9_appstream \ + --enablerepo=%%REPO_NAME_SERVER%% $MYSQL_SERVER_PACKAGE \ + && microdnf remove -y %%MYSQL_CONFIG_PKG_MINIMAL%% %%MYSQL_CONFIG_PKG%% \ + && microdnf clean all \ + && mkdir /docker-entrypoint-initdb.d + +COPY prepare-image.sh / +RUN /prepare-image.sh && rm -f /prepare-image.sh + +ENV MYSQL_UNIX_PORT /var/lib/mysql/mysql.sock + +COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /healthcheck.sh +ENTRYPOINT ["/entrypoint.sh"] +HEALTHCHECK CMD /healthcheck.sh +EXPOSE %%PORTS%% +CMD ["mysqld"] + diff --git a/mysql-server/template/control.rb b/mysql-server/template/control.rb new file mode 100644 index 000000000..ac449005f --- /dev/null +++ b/mysql-server/template/control.rb @@ -0,0 +1,20 @@ +control 'container' do + impact 0.5 + describe podman.containers do + its('status') { should cmp /Up/ } + its('commands') { should cmp /mysqld/ } + its('images') { should cmp /%%CONT_NAME%%:%%MAJOR_VERSION%%/ } + its('names') { should include "%%CONT_NAME%%-%%MAJOR_VERSION%%" } + end +end +control 'packages' do + impact 0.5 + describe package('%%MYSQL_SERVER_PACKAGE_NAME%%') do + it { should be_installed } + its ('version') { should match '%%MYSQL_SERVER_VERSION%%.*' } + end + describe package('%%MYSQL_SHELL_PACKAGE_NAME%%') do + it { should be_installed } + its ('version') { should match '%%MYSQL_SHELL_VERSION%%.*' } + end +end diff --git a/mysql-server/template/docker-entrypoint.sh b/mysql-server/template/docker-entrypoint.sh new file mode 100644 index 000000000..6052c591a --- /dev/null +++ b/mysql-server/template/docker-entrypoint.sh @@ -0,0 +1,230 @@ +#!/bin/bash +# Copyright (c) 2017, 2021, Oracle and/or its affiliates. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +set -e + +echo "[Entrypoint] MySQL Docker Image %%FULL_SERVER_VERSION%%" +# 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() { + local conf="$1"; shift + "$@" --verbose --help 2>/dev/null | grep "^$conf" | awk '$1 == "'"$conf"'" { print $2; exit }' +} + +# Generate a random password +_mkpw() { + letter=$(cat /dev/urandom| tr -dc a-zA-Z | dd bs=1 count=16 2> /dev/null ) + number=$(cat /dev/urandom| tr -dc 0-9 | dd bs=1 count=8 2> /dev/null) + special=$(cat /dev/urandom| tr -dc '=+@#%^&*_.,;:?/' | dd bs=1 count=8 2> /dev/null) + + echo $letter$number$special | fold -w 1 | shuf | tr -d '\n' +} + +# If command starts with an option, prepend mysqld +# This allows users to add command-line options without +# needing to specify the "mysqld" command +if [ "${1:0:1}" = '-' ]; then + set -- mysqld "$@" +fi + +# Check if entrypoint (and the container) is running as root +if [ $(id -u) = "0" ]; then + is_root=1 + install_devnull="install /dev/null -m0600 -omysql -gmysql" + MYSQLD_USER=mysql +else + install_devnull="install /dev/null -m0600" + MYSQLD_USER=$(id -u) +fi + +if [ "$1" = 'mysqld' ]; then + # Test that the server can start. We redirect stdout to /dev/null so + # only the error messages are left. + result=0 + %%VALIDATE_CONFIG%% + if [ ! "$result" = "0" ]; then + echo >&2 '[Entrypoint] ERROR: Unable to start MySQL. Please check your configuration.' + echo >&2 "[Entrypoint] $output" + exit 1 + fi + + # Get config + DATADIR="$(_get_config 'datadir' "$@")" + SOCKET="$(_get_config 'socket' "$@")" + + if [ ! -d "$DATADIR/mysql" ]; then + # If the password variable is a filename we use the contents of the file. We + # read this first to make sure that a proper error is generated for empty files. + if [ -f "$MYSQL_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(cat $MYSQL_ROOT_PASSWORD)" + if [ -z "$MYSQL_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] Empty MYSQL_ROOT_PASSWORD file specified.' + exit 1 + fi + fi + if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + echo >&2 '[Entrypoint] No password option specified for new database.' + echo >&2 '[Entrypoint] A random onetime password will be generated.' + MYSQL_RANDOM_ROOT_PASSWORD=true + MYSQL_ONETIME_PASSWORD=true + fi + if [ ! -d "$DATADIR" ]; then + mkdir -p "$DATADIR" + chown mysql:mysql "$DATADIR" + fi + + # The user can set a default_timezone either in a my.cnf file + # they mount into the container or on command line + # (`docker run mysql/mysql-server:8.0 --default-time-zone=Europe/Berlin`) + # however the timezone tables will only be populated in a later + # stage of this script. By using +00:00 as timezone we override + # the user's choice during initialization. Later the server + # will be restarted using the user's option. + + echo '[Entrypoint] Initializing database' + "$@" --user=$MYSQLD_USER --initialize-insecure --default-time-zone=+00:00 + + echo '[Entrypoint] Database initialized' + "$@" --user=$MYSQLD_USER --daemonize --skip-networking --socket="$SOCKET" --default-time-zone=+00:00 + + # To avoid using password on commandline, put it in a temporary file. + # The file is only populated when and if the root password is set. + PASSFILE=$(mktemp -u /var/lib/mysql-files/XXXXXXXXXX) + $install_devnull "$PASSFILE" + # Define the client command used throughout the script + # "SET @@SESSION.SQL_LOG_BIN=0;" is required for products like group replication to work properly + mysql=( mysql --defaults-extra-file="$PASSFILE" --protocol=socket -uroot -hlocalhost --socket="$SOCKET" --init-command="SET @@SESSION.SQL_LOG_BIN=0;") + + for i in {30..0}; do + if mysqladmin --socket="$SOCKET" ping &>/dev/null; then + break + fi + echo '[Entrypoint] Waiting for server...' + sleep 1 + done + if [ "$i" = 0 ]; then + echo >&2 '[Entrypoint] Timeout during MySQL init.' + exit 1 + fi + + mysql_tzinfo_to_sql /usr/share/zoneinfo | "${mysql[@]}" mysql + + if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then + MYSQL_ROOT_PASSWORD="$(_mkpw)" + echo "[Entrypoint] GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD" + fi + if [ -z "$MYSQL_ROOT_HOST" ]; then + ROOTCREATE="%%PASSWORDSET%%" + else + ROOTCREATE="%%PASSWORDSET%% \ + CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}'; \ + GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ; \ + GRANT PROXY ON ''@'' TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;" + fi + "${mysql[@]}" <<-EOSQL + DELETE FROM mysql.user WHERE user NOT IN ('mysql.infoschema', 'mysql.session', 'mysql.sys', 'root') OR host NOT IN ('localhost'); + CREATE USER 'healthchecker'@'localhost' IDENTIFIED BY 'healthcheckpass'; + ${ROOTCREATE} + FLUSH PRIVILEGES ; + EOSQL + if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then + # Put the password into the temporary config file + cat >"$PASSFILE" < "$SQL" +ALTER USER 'root'@'${MYSQL_ROOT_HOST}' PASSWORD EXPIRE; +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + else + cat << EOF > "$SQL" +ALTER USER 'root'@'localhost' PASSWORD EXPIRE; +EOF + fi + set -- "$@" --init-file="$SQL" + unset SQL + fi + + echo + echo '[Entrypoint] MySQL init process done. Ready for start up.' + echo + fi + + # Used by healthcheck to make sure it doesn't mistakenly report container + # healthy during startup + # Put the password into the temporary config file + touch /var/lib/mysql-files/healthcheck.cnf + cat >"/var/lib/mysql-files/healthcheck.cnf" <(mysql-'"$version"'.*-linux.*-x86_64\.tar\.gz)<' \ - | sed -r 's!.*\(mysql-([^<)]+)-linux.*-x86_64\.tar\.gz\).*!\1!' \ - | sort -V | tail -1)" - - ( - set -x - sed -ri ' - s/^(ENV MYSQL_MAJOR) .*/\1 '"$version"'/; - s/^(ENV MYSQL_VERSION) .*/\1 '"$fullVersion"'/ - ' "$version/Dockerfile" - ) -done