From cbada8aef29c45f3baf8cd1ab9db536ef9c38765 Mon Sep 17 00:00:00 2001 From: Sergey Zabolotny Date: Thu, 25 Oct 2018 11:19:51 +0300 Subject: [PATCH 1/3] Added healthcheck support. Updated entrypoint.sh for mysql 8.0 --- .travis.yml | 2 +- mysql-5.5/Dockerfile | 5 ++++ mysql-5.5/healthcheck.sh | 5 ++++ mysql-5.6/Dockerfile | 5 ++++ mysql-5.6/healthcheck.sh | 5 ++++ mysql-5.7/Dockerfile | 5 ++++ mysql-5.7/healthcheck.sh | 5 ++++ mysql-8.0/Dockerfile | 5 ++++ mysql-8.0/docker-entrypoint.sh | 42 ++++++++++++++++------------ mysql-8.0/healthcheck.sh | 5 ++++ tests/test.bats | 51 +++++++++++++++++++++++++++++++++- 11 files changed, 115 insertions(+), 20 deletions(-) create mode 100755 mysql-5.5/healthcheck.sh create mode 100755 mysql-5.6/healthcheck.sh create mode 100755 mysql-5.7/healthcheck.sh create mode 100755 mysql-8.0/healthcheck.sh diff --git a/.travis.yml b/.travis.yml index 168c5c2..90fc326 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,7 +14,7 @@ env: - VERSION=mysql-8.0 install: - - curl -fsSL get.docksal.io | sh + - curl -fsSL get.docksal.io | bash - fin version - fin sysinfo diff --git a/mysql-5.5/Dockerfile b/mysql-5.5/Dockerfile index 0f5c759..03ac345 100644 --- a/mysql-5.5/Dockerfile +++ b/mysql-5.5/Dockerfile @@ -6,7 +6,12 @@ COPY default.cnf /etc/mysql/conf.d/10-default.cnf VOLUME /var/lib/mysql COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /opt/healthcheck.sh + ENTRYPOINT ["/entrypoint.sh"] EXPOSE 3306 CMD ["mysqld"] + +# Health check script +HEALTHCHECK --interval=5s --timeout=1s --retries=12 CMD ["/opt/healthcheck.sh"] diff --git a/mysql-5.5/healthcheck.sh b/mysql-5.5/healthcheck.sh new file mode 100755 index 0000000..3357894 --- /dev/null +++ b/mysql-5.5/healthcheck.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +mysqladmin ping -u root --password=$MYSQL_ROOT_PASSWORD | grep -i 'mysqld is alive' || exit 1 + +exit 0 diff --git a/mysql-5.6/Dockerfile b/mysql-5.6/Dockerfile index 6b9c8e6..de7e903 100644 --- a/mysql-5.6/Dockerfile +++ b/mysql-5.6/Dockerfile @@ -6,7 +6,12 @@ COPY default.cnf /etc/mysql/conf.d/10-default.cnf VOLUME /var/lib/mysql COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /opt/healthcheck.sh + ENTRYPOINT ["/entrypoint.sh"] EXPOSE 3306 CMD ["mysqld"] + +# Health check script +HEALTHCHECK --interval=5s --timeout=1s --retries=12 CMD ["/opt/healthcheck.sh"] diff --git a/mysql-5.6/healthcheck.sh b/mysql-5.6/healthcheck.sh new file mode 100755 index 0000000..3357894 --- /dev/null +++ b/mysql-5.6/healthcheck.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +mysqladmin ping -u root --password=$MYSQL_ROOT_PASSWORD | grep -i 'mysqld is alive' || exit 1 + +exit 0 diff --git a/mysql-5.7/Dockerfile b/mysql-5.7/Dockerfile index 446181b..99894e0 100644 --- a/mysql-5.7/Dockerfile +++ b/mysql-5.7/Dockerfile @@ -6,7 +6,12 @@ COPY default.cnf /etc/mysql/conf.d/10-default.cnf VOLUME /var/lib/mysql COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /opt/healthcheck.sh + ENTRYPOINT ["/entrypoint.sh"] EXPOSE 3306 CMD ["mysqld"] + +# Health check script +HEALTHCHECK --interval=5s --timeout=1s --retries=12 CMD ["/opt/healthcheck.sh"] diff --git a/mysql-5.7/healthcheck.sh b/mysql-5.7/healthcheck.sh new file mode 100755 index 0000000..3357894 --- /dev/null +++ b/mysql-5.7/healthcheck.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +mysqladmin ping -u root --password=$MYSQL_ROOT_PASSWORD | grep -i 'mysqld is alive' || exit 1 + +exit 0 diff --git a/mysql-8.0/Dockerfile b/mysql-8.0/Dockerfile index 8bf6943..3b51394 100644 --- a/mysql-8.0/Dockerfile +++ b/mysql-8.0/Dockerfile @@ -6,7 +6,12 @@ COPY default.cnf /etc/mysql/conf.d/10-default.cnf VOLUME /var/lib/mysql COPY docker-entrypoint.sh /entrypoint.sh +COPY healthcheck.sh /opt/healthcheck.sh + ENTRYPOINT ["/entrypoint.sh"] EXPOSE 3306 CMD ["mysqld"] + +# Health check script +HEALTHCHECK --interval=5s --timeout=1s --retries=12 CMD ["/opt/healthcheck.sh"] diff --git a/mysql-8.0/docker-entrypoint.sh b/mysql-8.0/docker-entrypoint.sh index 638e6bd..720ef6d 100755 --- a/mysql-8.0/docker-entrypoint.sh +++ b/mysql-8.0/docker-entrypoint.sh @@ -40,6 +40,24 @@ file_env() { unset "$fileVar" } +# usage: process_init_file FILENAME MYSQLCOMMAND... +# ie: process_init_file foo.sh mysql -uroot +# (process a single initializer file, based on its extension. we define this +# function here, so that initializer scripts (*.sh) can use the same logic, +# potentially recursively, or override the logic used in subsequent calls) +process_init_file() { + local f="$1"; shift + local mysql=( "$@" ) + + case "$f" in + *.sh) echo "$0: running $f"; . "$f" ;; + *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;; + *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;; + *) echo "$0: ignoring $f" ;; + esac + echo +} + _check_config() { toRun=( "$@" --verbose --help ) if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then @@ -59,20 +77,13 @@ _check_config() { # latter only show values present in config files, and not server defaults _get_config() { local conf="$1"; shift - "$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null | awk '$1 == "'"$conf"'" { print $2; exit }' + "$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null \ + | awk '$1 == "'"$conf"'" && /^[^ \t]/ { sub(/^[^ \t]+[ \t]+/, ""); print; exit }' + # match "datadir /some/path with/spaces in/it here" but not "--xyz=abc\n datadir (xyz)" } # allow the container to be started with `--user` if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then - # Docksal: copy custom settings (if mounted) from /var/www/.docksal/etc/mysql/my.cnf and fix permissions - project_config_file='/var/www/.docksal/etc/mysql/my.cnf' - echo "Including custom configuration from ${project_config_file}" - if [[ -f ${project_config_file} ]]; then - cp -a ${project_config_file} /etc/mysql/conf.d/99-overrides.cnf - chown -R root:root /etc/mysql/conf.d/* - chmod -R 644 /etc/mysql/conf.d/* - fi - _check_config "$@" DATADIR="$(_get_config 'datadir' "$@")" mkdir -p "$DATADIR" @@ -152,7 +163,7 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then -- or products like mysql-fabric won't work SET @@SESSION.SQL_LOG_BIN=0; - SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ; + ALTER USER 'root'@'localhost' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ; GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ; ${rootCreate} DROP DATABASE IF EXISTS test ; @@ -182,14 +193,9 @@ if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then fi echo + ls /docker-entrypoint-initdb.d/ > /dev/null for f in /docker-entrypoint-initdb.d/*; do - case "$f" in - *.sh) echo "$0: running $f"; . "$f" ;; - *.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;; - *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;; - *) echo "$0: ignoring $f" ;; - esac - echo + process_init_file "$f" "${mysql[@]}" done if [ ! -z "$MYSQL_ONETIME_PASSWORD" ]; then diff --git a/mysql-8.0/healthcheck.sh b/mysql-8.0/healthcheck.sh new file mode 100755 index 0000000..3357894 --- /dev/null +++ b/mysql-8.0/healthcheck.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +mysqladmin ping -u root --password=$MYSQL_ROOT_PASSWORD | grep -i 'mysqld is alive' || exit 1 + +exit 0 diff --git a/tests/test.bats b/tests/test.bats index a5ef46b..29ab642 100644 --- a/tests/test.bats +++ b/tests/test.bats @@ -13,6 +13,53 @@ teardown () { echo "================================================================" } +# Checks container health status (if available) +# @param $1 container id/name +_healthcheck () +{ + local health_status + health_status=$(docker inspect --format='{{json .State.Health.Status}}' "$1" 2>/dev/null) + + # Wait for 5s then exit with 0 if a container does not have a health status property + # Necessary for backward compatibility with images that do not support health checks + if [[ $? != 0 ]]; then + echo "Waiting 10s for container to start..." + sleep 10 + return 0 + fi + + # If it does, check the status + echo $health_status | grep '"healthy"' >/dev/null 2>&1 +} + +# Waits for containers to become healthy +# For reasoning why we are not using `depends_on` `condition` see here: +# https://github.com/docksal/docksal/issues/225#issuecomment-306604063 +_healthcheck_wait () +{ + # Wait for cli to become ready by watching its health status + local container_name="${NAME}" + local delay=5 + local timeout=30 + local elapsed=0 + + until _healthcheck "$container_name"; do + echo "Waiting for $container_name to become ready..." + sleep "$delay"; + + # Give the container 30s to become ready + elapsed=$((elapsed + delay)) + if ((elapsed > timeout)); then + echo-error "$container_name heathcheck failed" \ + "Container did not enter a healthy state within the expected amount of time." \ + "Try ${yellow}fin restart${NC}" + exit 1 + fi + done + + return 0 +} + # Global skip # Uncomment below, then comment skip in the test you want to debug. When done, reverse. #SKIP=1 @@ -22,7 +69,7 @@ teardown () { ### Setup ### make start - sleep 30 # TODO: replace with a healthcheck + _healthcheck_wait ### Tests ### # MySQL does a restart, so there should be two of these in the logs after a successful start @@ -32,6 +79,7 @@ teardown () { @test "Default database present" { [[ $SKIP == 1 ]] && skip + _healthcheck_wait run make mysql-query QUERY='SHOW DATABASES;' [[ "$output" =~ "default" ]] @@ -39,6 +87,7 @@ teardown () { @test "Check variables" { [[ $SKIP == 1 ]] && skip + _healthcheck_wait # Grab variables from the container # -s used to supress echoing of the actual make command From 139912831cade6e303092a3fc3d24ed7c5c2d908 Mon Sep 17 00:00:00 2001 From: Sergey Zabolotny Date: Fri, 26 Oct 2018 10:20:05 +0300 Subject: [PATCH 2/3] Use fixed mysql versions --- mysql-5.5/Dockerfile | 2 +- mysql-5.6/Dockerfile | 2 +- mysql-5.7/Dockerfile | 2 +- mysql-8.0/Dockerfile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-5.5/Dockerfile b/mysql-5.5/Dockerfile index 03ac345..88ea671 100644 --- a/mysql-5.5/Dockerfile +++ b/mysql-5.5/Dockerfile @@ -1,4 +1,4 @@ -FROM mysql:5.5 +FROM mysql:5.5.61 # Docksal settings COPY default.cnf /etc/mysql/conf.d/10-default.cnf diff --git a/mysql-5.6/Dockerfile b/mysql-5.6/Dockerfile index de7e903..75bced4 100644 --- a/mysql-5.6/Dockerfile +++ b/mysql-5.6/Dockerfile @@ -1,4 +1,4 @@ -FROM mysql:5.6 +FROM mysql:5.6.41 # Docksal settings COPY default.cnf /etc/mysql/conf.d/10-default.cnf diff --git a/mysql-5.7/Dockerfile b/mysql-5.7/Dockerfile index 99894e0..fefa572 100644 --- a/mysql-5.7/Dockerfile +++ b/mysql-5.7/Dockerfile @@ -1,4 +1,4 @@ -FROM mysql:5.7 +FROM mysql:5.7.24 # Docksal settings COPY default.cnf /etc/mysql/conf.d/10-default.cnf diff --git a/mysql-8.0/Dockerfile b/mysql-8.0/Dockerfile index 3b51394..4c2bbd5 100644 --- a/mysql-8.0/Dockerfile +++ b/mysql-8.0/Dockerfile @@ -1,4 +1,4 @@ -FROM mysql:8.0 +FROM mysql:8.0.13 # Docksal settings COPY default.cnf /etc/mysql/conf.d/10-default.cnf From 23b1b3d6319b2a76340a5897977e8bdb4295b34d Mon Sep 17 00:00:00 2001 From: Sergey Zabolotny Date: Tue, 6 Nov 2018 16:36:32 +0200 Subject: [PATCH 3/3] Restored custom docksal code in docker-entrypoint.sh, make healtcheck once after start service --- mysql-8.0/docker-entrypoint.sh | 9 +++++++++ tests/test.bats | 2 -- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/mysql-8.0/docker-entrypoint.sh b/mysql-8.0/docker-entrypoint.sh index 720ef6d..7c2197f 100755 --- a/mysql-8.0/docker-entrypoint.sh +++ b/mysql-8.0/docker-entrypoint.sh @@ -84,6 +84,15 @@ _get_config() { # allow the container to be started with `--user` if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then + # Docksal: copy custom settings (if mounted) from /var/www/.docksal/etc/mysql/my.cnf and fix permissions + project_config_file='/var/www/.docksal/etc/mysql/my.cnf' + echo "Including custom configuration from ${project_config_file}" + if [[ -f ${project_config_file} ]]; then + cp -a ${project_config_file} /etc/mysql/conf.d/99-overrides.cnf + chown -R root:root /etc/mysql/conf.d/* + chmod -R 644 /etc/mysql/conf.d/* + fi + _check_config "$@" DATADIR="$(_get_config 'datadir' "$@")" mkdir -p "$DATADIR" diff --git a/tests/test.bats b/tests/test.bats index 29ab642..1c3140f 100644 --- a/tests/test.bats +++ b/tests/test.bats @@ -79,7 +79,6 @@ _healthcheck_wait () @test "Default database present" { [[ $SKIP == 1 ]] && skip - _healthcheck_wait run make mysql-query QUERY='SHOW DATABASES;' [[ "$output" =~ "default" ]] @@ -87,7 +86,6 @@ _healthcheck_wait () @test "Check variables" { [[ $SKIP == 1 ]] && skip - _healthcheck_wait # Grab variables from the container # -s used to supress echoing of the actual make command