diff --git a/containers/ddev-dbserver/10.1/Dockerfile b/containers/ddev-dbserver/10.1/Dockerfile index f9c87ef8ea2..abedb559fab 100644 --- a/containers/ddev-dbserver/10.1/Dockerfile +++ b/containers/ddev-dbserver/10.1/Dockerfile @@ -1,4 +1,4 @@ -FROM mariadb:10.1.38-bionic +FROM mariadb:10.1.40-bionic ENV MYSQL_DATABASE db ENV MYSQL_USER db @@ -26,4 +26,4 @@ ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 3306 # The following line overrides any cmd entry CMD [] -HEALTHCHECK --interval=2s --retries=30 CMD ["/healthcheck.sh"] +HEALTHCHECK --interval=1s --retries=30 --timeout=120s CMD ["/healthcheck.sh"] diff --git a/containers/ddev-dbserver/10.1/files/docker-entrypoint.sh b/containers/ddev-dbserver/10.1/files/docker-entrypoint.sh index 1721405451f..53e905f9154 100755 --- a/containers/ddev-dbserver/10.1/files/docker-entrypoint.sh +++ b/containers/ddev-dbserver/10.1/files/docker-entrypoint.sh @@ -4,6 +4,7 @@ set -eu set -o pipefail SOCKET=/var/tmp/mysql.sock +rm -f /tmp/healthy # Wait for mysql server to be ready. function serverwait { diff --git a/containers/ddev-dbserver/10.1/files/healthcheck.sh b/containers/ddev-dbserver/10.1/files/healthcheck.sh index cbc17d21910..007c4346483 100644 --- a/containers/ddev-dbserver/10.1/files/healthcheck.sh +++ b/containers/ddev-dbserver/10.1/files/healthcheck.sh @@ -3,6 +3,25 @@ ## mysql health check for docker. original source: https://github.com/docker-library/healthcheck/blob/master/mysql/docker-healthcheck set -eo pipefail +sleeptime=59 -mysql --host=127.0.0.1 -udb -pdb --database=db -e "SHOW DATABASES LIKE 'db';" >/dev/null +# Since docker doesn't provide a lazy period for startup, +# we track health. If the last check showed healthy +# as determined by existence of /tmp/healthy, then +# sleep at startup. This requires the timeout to be set +# higher than the sleeptime used here. +if [ -f /tmp/healthy ]; then + printf "container was previously healthy, so sleeping ${sleeptime} seconds before continuing healthcheck... " + sleep ${sleeptime} +fi + + +if mysql --host=127.0.0.1 -udb -pdb --database=db -e "SHOW DATABASES LIKE 'db';" >/dev/null; then + printf "healthy" + touch /tmp/healthy + exit 0 +fi + +rm -f /tmp/healthy +exit 1 diff --git a/containers/ddev-dbserver/10.2/Dockerfile b/containers/ddev-dbserver/10.2/Dockerfile index 6d3b6d07721..bcf13e0fb17 100644 --- a/containers/ddev-dbserver/10.2/Dockerfile +++ b/containers/ddev-dbserver/10.2/Dockerfile @@ -1,4 +1,4 @@ -FROM mariadb:10.2.22 +FROM mariadb:10.2.25 ENV MYSQL_DATABASE db ENV MYSQL_USER db @@ -26,4 +26,4 @@ ENTRYPOINT ["/docker-entrypoint.sh"] EXPOSE 3306 # The following line overrides any cmd entry CMD [] -HEALTHCHECK --interval=2s --retries=30 CMD ["/healthcheck.sh"] +HEALTHCHECK --interval=1s --retries=30 --timeout=120s CMD ["/healthcheck.sh"] diff --git a/containers/ddev-dbserver/10.2/files/docker-entrypoint.sh b/containers/ddev-dbserver/10.2/files/docker-entrypoint.sh index e4f4e83d3c4..6679d573778 100755 --- a/containers/ddev-dbserver/10.2/files/docker-entrypoint.sh +++ b/containers/ddev-dbserver/10.2/files/docker-entrypoint.sh @@ -5,6 +5,8 @@ set -o pipefail SOCKET=/var/tmp/mysql.sock +rm -f /tmp/healthy + # Wait for mysql server to be ready. function serverwait { for i in {60..0}; diff --git a/containers/ddev-dbserver/10.2/files/healthcheck.sh b/containers/ddev-dbserver/10.2/files/healthcheck.sh index cbc17d21910..007c4346483 100644 --- a/containers/ddev-dbserver/10.2/files/healthcheck.sh +++ b/containers/ddev-dbserver/10.2/files/healthcheck.sh @@ -3,6 +3,25 @@ ## mysql health check for docker. original source: https://github.com/docker-library/healthcheck/blob/master/mysql/docker-healthcheck set -eo pipefail +sleeptime=59 -mysql --host=127.0.0.1 -udb -pdb --database=db -e "SHOW DATABASES LIKE 'db';" >/dev/null +# Since docker doesn't provide a lazy period for startup, +# we track health. If the last check showed healthy +# as determined by existence of /tmp/healthy, then +# sleep at startup. This requires the timeout to be set +# higher than the sleeptime used here. +if [ -f /tmp/healthy ]; then + printf "container was previously healthy, so sleeping ${sleeptime} seconds before continuing healthcheck... " + sleep ${sleeptime} +fi + + +if mysql --host=127.0.0.1 -udb -pdb --database=db -e "SHOW DATABASES LIKE 'db';" >/dev/null; then + printf "healthy" + touch /tmp/healthy + exit 0 +fi + +rm -f /tmp/healthy +exit 1 diff --git a/containers/ddev-router/Dockerfile b/containers/ddev-router/Dockerfile index 7c2e12d558e..a799250fa10 100644 --- a/containers/ddev-router/Dockerfile +++ b/containers/ddev-router/Dockerfile @@ -1,4 +1,4 @@ -FROM nginx:1.15.12 +FROM nginx:1.17.0 ENV MKCERT_VERSION=v1.3.0 @@ -34,4 +34,4 @@ ENTRYPOINT ["/app/docker-entrypoint.sh"] CMD ["forego", "start", "-r"] WORKDIR /app/ -HEALTHCHECK --interval=5s --retries=5 CMD /app/healthcheck.sh +HEALTHCHECK --interval=1s --retries=10 --timeout=120s --start-period=10s CMD /app/healthcheck.sh diff --git a/containers/ddev-router/docker-entrypoint.sh b/containers/ddev-router/docker-entrypoint.sh index a344918cbe0..8cb65c7bedd 100755 --- a/containers/ddev-router/docker-entrypoint.sh +++ b/containers/ddev-router/docker-entrypoint.sh @@ -1,6 +1,8 @@ #!/bin/bash set -e +rm -f /tmp/healthy + # Warn if the DOCKER_HOST socket does not exist if [[ $DOCKER_HOST = unix://* ]]; then socket_file=${DOCKER_HOST#unix://} diff --git a/containers/ddev-router/healthcheck.sh b/containers/ddev-router/healthcheck.sh index 97b25b2515d..5e3678fa0ce 100644 --- a/containers/ddev-router/healthcheck.sh +++ b/containers/ddev-router/healthcheck.sh @@ -2,7 +2,39 @@ set -eu set -o pipefail -# Check nginx config -nginx -t || exit 1 +sleeptime=59 + +# Since docker doesn't provide a lazy period for startup, +# we track health. If the last check showed healthy +# as determined by existence of /tmp/healthy, then +# sleep at startup. This requires the timeout to be set +# higher than the sleeptime used here. +if [ -f /tmp/healthy ]; then + printf "container was previously healthy, so sleeping ${sleeptime} seconds before continuing healthcheck... " + sleep ${sleeptime} +fi + +config=false +connect=false + +if nginx -t ; then + config=true + printf "nginx config: OK " +fi + # Check our healthcheck endpoint -curl --fail --connect-timeout 2 --retry 2 http://127.0.0.1/healthcheck || (echo "ddev-router healthcheck endpoint not responding" && exit 2) +if curl --fail --connect-timeout 2 --retry 2 http://127.0.0.1/healthcheck; then + connect=true + echo "nginx healthcheck endpoint: OK " +else + echo "ddev-router healthcheck endpoint not responding " +fi + +if [ ${config} = true -a ${connect} = true ]; then + printf "healthy" + touch /tmp/healthy + exit 0 +fi + +rm -f /tmp/healthy +exit 1 diff --git a/containers/ddev-ssh-agent/Dockerfile b/containers/ddev-ssh-agent/Dockerfile index fa7e30a91f1..af1abbc1e45 100644 --- a/containers/ddev-ssh-agent/Dockerfile +++ b/containers/ddev-ssh-agent/Dockerfile @@ -22,7 +22,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -FROM alpine:3.8 +FROM alpine:3.10 # Install dependencies RUN apk add --no-cache \ @@ -48,7 +48,7 @@ RUN ln -s $SSH_KEY_DIR /home/.ssh RUN mkdir ${SOCKET_DIR} && mkdir ${SSH_KEY_DIR} && chmod 777 ${SOCKET_DIR} ${SSH_KEY_DIR} -HEALTHCHECK --interval=2s --retries=5 CMD ["/healthcheck.sh"] +HEALTHCHECK --interval=1s --retries=5 --timeout=120s CMD ["/healthcheck.sh"] VOLUME ${SOCKET_DIR} diff --git a/containers/ddev-ssh-agent/files/entry.sh b/containers/ddev-ssh-agent/files/entry.sh index 70dcaada694..6d310bbe2d0 100755 --- a/containers/ddev-ssh-agent/files/entry.sh +++ b/containers/ddev-ssh-agent/files/entry.sh @@ -21,6 +21,7 @@ set -eo pipefail +rm -f /tmp/healthy # Print a debug message if debug mode is on ($DEBUG is not empty) # @param message diff --git a/containers/ddev-ssh-agent/files/healthcheck.sh b/containers/ddev-ssh-agent/files/healthcheck.sh index 1f0b9b9261f..b4563be36a9 100755 --- a/containers/ddev-ssh-agent/files/healthcheck.sh +++ b/containers/ddev-ssh-agent/files/healthcheck.sh @@ -3,7 +3,23 @@ # ddev-ssh-agent healthcheck set -eo pipefail +sleeptime=59 # Make sure that both socat and ssh-agent are running -killall -0 socat && killall -0 ssh-agent +# Since docker doesn't provide a lazy period for startup, +# we track health. If the last check showed healthy +# as determined by existence of /tmp/healthy, then +# sleep at startup. This requires the timeout to be set +# higher than the sleeptime used here. +if [ -f /tmp/healthy ]; then + printf "container was previously healthy, so sleeping ${sleeptime} seconds before continuing healthcheck... " + sleep ${sleeptime} +fi +if killall -0 socat ssh-agent; then + printf "healthy" + touch /tmp/healthy + exit 0 +fi +rm -f /tmp/healthy +exit 1 diff --git a/containers/ddev-webserver/Dockerfile b/containers/ddev-webserver/Dockerfile index f4c81ac9b5f..50fc55b8c35 100644 --- a/containers/ddev-webserver/Dockerfile +++ b/containers/ddev-webserver/Dockerfile @@ -151,6 +151,6 @@ RUN chmod ugo+x /start.sh /healthcheck.sh EXPOSE 80 8025 -HEALTHCHECK --interval=3s --retries=6 CMD ["/healthcheck.sh"] +HEALTHCHECK --interval=1s --retries=10 --timeout=120s CMD ["/healthcheck.sh"] CMD ["/start.sh"] diff --git a/containers/ddev-webserver/scripts/healthcheck.sh b/containers/ddev-webserver/scripts/healthcheck.sh index b6b692eb316..4c87c6ab8a6 100755 --- a/containers/ddev-webserver/scripts/healthcheck.sh +++ b/containers/ddev-webserver/scripts/healthcheck.sh @@ -4,6 +4,49 @@ set -eo pipefail -curl --fail -s 127.0.0.1/phpstatus >/dev/null && printf "phpstatus: OK, " || (printf "phpstatus FAILED" && exit 1) -ls /var/www/html >/dev/null && printf "/var/www/html: OK, " || (printf "/var/www/html access FAILED" && exit 2) -curl --fail -s localhost:8025 >/dev/null && printf "mailhog: OK" || (printf "mailhog FAILED" && exit 3) +sleeptime=59 + +# Make sure that both phpstatus, mounted code, and mailhog +# are working. +# Since docker doesn't provide a lazy period for startup, +# we track health. If the last check showed healthy +# as determined by existence of /tmp/healthy, then +# sleep at startup. This requires the timeout to be set +# higher than the sleeptime used here. +if [ -f /tmp/healthy ]; then + printf "container was previously healthy, so sleeping ${sleeptime} seconds before continuing healthcheck... " + sleep ${sleeptime} +fi + +phpstatus=false +htmlaccess=false +mailhog=false +if curl --fail -s 127.0.0.1/phpstatus >/dev/null ; then + phpstatus=true + printf "phpstatus: OK " +else + printf "phpstatus FAILED " +fi + +if ls /var/www/html >/dev/null; then + htmlstatus=true + printf "/var/www/html: OK " +else + printf "/var/www/html access FAILED" +fi + +if curl --fail -s localhost:8025 >/dev/null; then + mailhog=true + printf "mailhog: OK " ; +else + printf "mailhog FAILED " +fi + +if ${phpstatus} = true -a ${htmlaccess} = true -a ${mailhog} = true ; then + touch /tmp/healthy + exit 0 +fi +rm -f /tmp/healthy +exit 1 + + diff --git a/containers/ddev-webserver/scripts/start.sh b/containers/ddev-webserver/scripts/start.sh index 1a055aa296a..8c9b183ef86 100755 --- a/containers/ddev-webserver/scripts/start.sh +++ b/containers/ddev-webserver/scripts/start.sh @@ -2,6 +2,8 @@ set -x set -o errexit nounset pipefail +rm -f /tmp/healthy + # If DDEV_PHP_VERSION isn't set, use a reasonable default DDEV_PHP_VERSION="${DDEV_PHP_VERSION:-$PHP_DEFAULT_VERSION}" diff --git a/pkg/ddevapp/templates.go b/pkg/ddevapp/templates.go index 7263e081b1f..3681acd5973 100644 --- a/pkg/ddevapp/templates.go +++ b/pkg/ddevapp/templates.go @@ -40,9 +40,10 @@ services: - TZ={{ .Timezone }} command: "$DDEV_MARIADB_LOCAL_COMMAND" healthcheck: - interval: 5s - retries: 12 - start_period: 60s + interval: 1s + retries: 10 + start_period: 10s + timeout: 120s web: container_name: {{ .Plugin }}-${DDEV_SITENAME}-web {{ if .WebBuildContext }} @@ -114,9 +115,10 @@ services: {{ range $hostname := .Hostnames }}- "ddev-router:{{ $hostname }}" {{ end }} healthcheck: - interval: 4s - retries: 6 + interval: 1s + retries: 10 start_period: 10s + timeout: 120s {{ if .WebcacheEnabled }} bgsync: container_name: ddev-${DDEV_SITENAME}-bgsync @@ -168,7 +170,7 @@ services: # HTTP_EXPOSE allows for ports accepting HTTP traffic to be accessible from .ddev.site: - HTTP_EXPOSE=${DDEV_PHPMYADMIN_PORT}:{{ .DBAPort }} healthcheck: - interval: 90s + interval: 120s timeout: 2s retries: 1 @@ -397,9 +399,10 @@ services: - ddev-global-cache:/mnt/ddev-global-cache:rw restart: "no" healthcheck: - interval: 6s - retries: 6 + interval: 1s + retries: 10 start_period: 10s + timeout: 120s networks: default: @@ -427,8 +430,10 @@ services: environment: - SSH_AUTH_SOCK=/tmp/.ssh-agent/socket healthcheck: - interval: 2s - retries: 5 + interval: 1s + retries: 2 + start_period: 10s + timeout: 62s networks: default: external: diff --git a/pkg/dockerutil/dockerutils_test.go b/pkg/dockerutil/dockerutils_test.go index d5e3e0148cf..74f2beb7f5e 100644 --- a/pkg/dockerutil/dockerutils_test.go +++ b/pkg/dockerutil/dockerutils_test.go @@ -64,7 +64,6 @@ func TestMain(m *testing.M) { }, Env: []string{"HOTDOG=superior-to-corndog", "POTATO=future-fry"}, }, - // "PortBindings": { "22/tcp": [{ "HostPort": "11022" }] }, HostConfig: &docker.HostConfig{ PortBindings: map[docker.Port][]docker.PortBinding{ "80/tcp": { @@ -127,11 +126,11 @@ func TestGetContainerHealth(t *testing.T) { healthDetail, err := ContainerWait(15, labels) assert.NoError(err) - assert.Equal("phpstatus: OK, /var/www/html: OK, mailhog: OK", healthDetail) + assert.Equal("phpstatus: OK /var/www/html: OK mailhog: OK ", healthDetail) status, healthDetail = GetContainerHealth(container) assert.Equal(status, "healthy") - assert.Equal("phpstatus: OK, /var/www/html: OK, mailhog: OK", healthDetail) + assert.Equal("phpstatus: OK /var/www/html: OK mailhog: OK ", healthDetail) } // TestContainerWait tests the error cases for the container check wait loop. diff --git a/pkg/version/version.go b/pkg/version/version.go index 3dd697bf9f5..c2e38dfd215 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -45,13 +45,13 @@ var DockerComposeFileFormatVersion = "3.6" var WebImg = "drud/ddev-webserver" // WebTag defines the default web image tag for drud dev -var WebTag = "20190626_apache" // Note that this can be overridden by make +var WebTag = "20190626_healthcheck" // Note that this can be overridden by make // DBImg defines the default db image used for applications. var DBImg = "drud/ddev-dbserver" // BaseDBTag is the main tag, DBTag is constructed from it -var BaseDBTag = "v1.9.0" +var BaseDBTag = "20190626_healthcheck" // DBAImg defines the default phpmyadmin image tag used for applications. var DBAImg = "drud/phpmyadmin" @@ -69,11 +69,11 @@ var BgsyncTag = "v1.9.0" // Note that this can be overridden by make var RouterImage = "drud/ddev-router" // RouterTag defines the tag used for the router. -var RouterTag = "v1.9.0" // Note that this can be overridden by make +var RouterTag = "20190626_healthcheck" // Note that this can be overridden by make var SSHAuthImage = "drud/ddev-ssh-agent" -var SSHAuthTag = "v1.9.0" +var SSHAuthTag = "20190626_healthcheck" // COMMIT is the actual committish, supplied by make var COMMIT = "COMMIT should be overridden"