From 8f5bcc1c980fce198bd191cfb7f51a3e76bb59cd Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 30 Dec 2020 17:24:03 -0800 Subject: [PATCH] Add new "wp-config-docker.php" that uses "getenv" for configuration This new method of configuration allows us to stop modifying the user-supplied `wp-config.php` file on every container startup, and instead just let PHP itself read the values directly from the source. With this change, the "beta" tags are force-reenabled at the same version as the latest releases to allow users to test this before the next release of WordPress (where it is intended that this change will go live for all image variants). --- .gitattributes | 1 + Dockerfile.template | 3 + apply-templates.sh | 3 + beta/php7.3/apache/Dockerfile | 1 + beta/php7.3/apache/docker-entrypoint.sh | 250 +++----------------- beta/php7.3/apache/wp-config-docker.php | 120 ++++++++++ beta/php7.3/fpm-alpine/Dockerfile | 1 + beta/php7.3/fpm-alpine/docker-entrypoint.sh | 250 +++----------------- beta/php7.3/fpm-alpine/wp-config-docker.php | 120 ++++++++++ beta/php7.3/fpm/Dockerfile | 1 + beta/php7.3/fpm/docker-entrypoint.sh | 250 +++----------------- beta/php7.3/fpm/wp-config-docker.php | 120 ++++++++++ beta/php7.4/apache/Dockerfile | 1 + beta/php7.4/apache/docker-entrypoint.sh | 250 +++----------------- beta/php7.4/apache/wp-config-docker.php | 120 ++++++++++ beta/php7.4/fpm-alpine/Dockerfile | 1 + beta/php7.4/fpm-alpine/docker-entrypoint.sh | 250 +++----------------- beta/php7.4/fpm-alpine/wp-config-docker.php | 120 ++++++++++ beta/php7.4/fpm/Dockerfile | 1 + beta/php7.4/fpm/docker-entrypoint.sh | 250 +++----------------- beta/php7.4/fpm/wp-config-docker.php | 120 ++++++++++ docker-entrypoint-ng.sh | 91 +++++++ generate-stackbrew-library.sh | 2 +- wp-config-docker.php | 120 ++++++++++ 24 files changed, 1113 insertions(+), 1333 deletions(-) create mode 100644 beta/php7.3/apache/wp-config-docker.php create mode 100644 beta/php7.3/fpm-alpine/wp-config-docker.php create mode 100644 beta/php7.3/fpm/wp-config-docker.php create mode 100644 beta/php7.4/apache/wp-config-docker.php create mode 100644 beta/php7.4/fpm-alpine/wp-config-docker.php create mode 100644 beta/php7.4/fpm/wp-config-docker.php create mode 100755 docker-entrypoint-ng.sh create mode 100644 wp-config-docker.php diff --git a/.gitattributes b/.gitattributes index 9396a6bec9..3395257686 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ /*/**/Dockerfile linguist-generated /*/**/docker-entrypoint.sh linguist-generated +/*/**/wp-config-docker.php linguist-generated /Dockerfile.template linguist-language=Dockerfile diff --git a/Dockerfile.template b/Dockerfile.template index 705a21b462..a12053ced0 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -229,6 +229,9 @@ RUN set -ex; \ VOLUME /var/www/html +{{ if env.version == "beta" then ( -}} +COPY --chown=www-data:www-data wp-config-docker.php /usr/src/wordpress/ +{{ ) else "" end -}} COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] diff --git a/apply-templates.sh b/apply-templates.sh index ed3ad604ce..0d820fbdd6 100755 --- a/apply-templates.sh +++ b/apply-templates.sh @@ -52,6 +52,9 @@ for version; do if [ "$version" = 'cli' ]; then cp -a cli-entrypoint.sh "$dir/docker-entrypoint.sh" + elif [ "$version" = 'beta' ]; then + cp -a docker-entrypoint-ng.sh "$dir/docker-entrypoint.sh" + cp -a wp-config-docker.php "$dir/" else cp -a docker-entrypoint.sh "$dir/" fi diff --git a/beta/php7.3/apache/Dockerfile b/beta/php7.3/apache/Dockerfile index 76401c5b13..47783e7a9e 100644 --- a/beta/php7.3/apache/Dockerfile +++ b/beta/php7.3/apache/Dockerfile @@ -143,6 +143,7 @@ RUN set -eux; \ VOLUME /var/www/html +COPY --chown=www-data:www-data wp-config-docker.php /usr/src/wordpress/ COPY docker-entrypoint.sh /usr/local/bin/ ENTRYPOINT ["docker-entrypoint.sh"] diff --git a/beta/php7.3/apache/docker-entrypoint.sh b/beta/php7.3/apache/docker-entrypoint.sh index 6a40c02b5f..0fca21c79d 100755 --- a/beta/php7.3/apache/docker-entrypoint.sh +++ b/beta/php7.3/apache/docker-entrypoint.sh @@ -1,30 +1,10 @@ -#!/bin/bash -set -euo pipefail +#!/usr/bin/env bash +set -Eeuo pipefail -# usage: file_env VAR [DEFAULT] -# ie: file_env 'XYZ_DB_PASSWORD' 'example' -# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of -# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) -file_env() { - local var="$1" - local fileVar="${var}_FILE" - local def="${2:-}" - if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then - echo >&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then - if [ "$(id -u)" = '0' ]; then +if [[ "$1" == apache2* ]] || [ "$1" = 'php-fpm' ]; then + uid="$(id -u)" + gid="$(id -g)" + if [ "$uid" = '0' ]; then case "$1" in apache2*) user="${APACHE_RUN_USER:-www-data}" @@ -41,13 +21,13 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then ;; esac else - user="$(id -u)" - group="$(id -g)" + user="$uid" + group="$gid" fi if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then # if the directory exists and WordPress doesn't appear to be installed AND the permissions of it are root:root, let's chown it (likely a Docker-created directory) - if [ "$(id -u)" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then + if [ "$uid" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then chown "$user:$group" . fi @@ -65,7 +45,7 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then --extract --file - ) - if [ "$user" != '0' ]; then + if [ "$uid" != '0' ]; then # avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted" targetTarArgs+=( --no-overwrite-dir ) fi @@ -84,202 +64,28 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then echo >&2 "Complete! WordPress has been successfully copied to $PWD" fi - # allow any of these "Authentication Unique Keys and Salts." to be specified via - # environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY") - uniqueEnvs=( - AUTH_KEY - SECURE_AUTH_KEY - LOGGED_IN_KEY - NONCE_KEY - AUTH_SALT - SECURE_AUTH_SALT - LOGGED_IN_SALT - NONCE_SALT - ) - envs=( - WORDPRESS_DB_HOST - WORDPRESS_DB_USER - WORDPRESS_DB_PASSWORD - WORDPRESS_DB_NAME - WORDPRESS_DB_CHARSET - WORDPRESS_DB_COLLATE - "${uniqueEnvs[@]/#/WORDPRESS_}" - WORDPRESS_TABLE_PREFIX - WORDPRESS_DEBUG - WORDPRESS_CONFIG_EXTRA - ) - haveConfig= - for e in "${envs[@]}"; do - file_env "$e" - if [ -z "$haveConfig" ] && [ -n "${!e}" ]; then - haveConfig=1 - fi - done - - # linking backwards-compatibility - if [ -n "${!MYSQL_ENV_MYSQL_*}" ]; then - haveConfig=1 - # host defaults to "mysql" below if unspecified - : "${WORDPRESS_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}}" - if [ "$WORDPRESS_DB_USER" = 'root' ]; then - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" - else - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_PASSWORD:-}}" - fi - : "${WORDPRESS_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-}}" - fi - - # only touch "wp-config.php" if we have environment-supplied configuration values - if [ "$haveConfig" ]; then - : "${WORDPRESS_DB_HOST:=mysql}" - : "${WORDPRESS_DB_USER:=root}" - : "${WORDPRESS_DB_PASSWORD:=}" - : "${WORDPRESS_DB_NAME:=wordpress}" - : "${WORDPRESS_DB_CHARSET:=utf8}" - : "${WORDPRESS_DB_COLLATE:=}" - - # version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks - # https://github.com/docker-library/wordpress/issues/116 - # https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4 - sed -ri -e 's/\r$//' wp-config* - - if [ ! -e wp-config.php ]; then - awk ' - /^\/\*.*stop editing.*\*\/$/ && c == 0 { - c = 1 - system("cat") - if (ENVIRON["WORDPRESS_CONFIG_EXTRA"]) { - print "// WORDPRESS_CONFIG_EXTRA" - print ENVIRON["WORDPRESS_CONFIG_EXTRA"] "\n" + wpEnvs=( "${!WORDPRESS_@}" ) + if [ ! -s wp-config.php ] && [ "${#wpEnvs[@]}" -gt 0 ]; then + for wpConfigDocker in \ + wp-config-docker.php \ + /usr/src/wordpress/wp-config-docker.php \ + ; do + if [ -s "$wpConfigDocker" ]; then + echo >&2 "No 'wp-config.php' found in $PWD, but 'WORDPRESS_...' variables supplied; copying '$wpConfigDocker' (${wpEnvs[*]})" + # using "awk" to replace all instances of "put your unique phrase here" with a properly unique string (for AUTH_KEY and friends to have safe defaults if they aren't specified with environment variables) + awk ' + /put your unique phrase here/ { + cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1" + cmd | getline str + close(cmd) + gsub("put your unique phrase here", str) } - } - { print } - ' wp-config-sample.php > wp-config.php <<'EOPHP' -// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact -// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy -if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { - $_SERVER['HTTPS'] = 'on'; -} - -EOPHP - chown "$user:$group" wp-config.php - elif [ -e wp-config.php ] && [ -n "$WORDPRESS_CONFIG_EXTRA" ] && [[ "$(< wp-config.php)" != *"$WORDPRESS_CONFIG_EXTRA"* ]]; then - # (if the config file already contains the requested PHP code, don't print a warning) - echo >&2 - echo >&2 'WARNING: environment variable "WORDPRESS_CONFIG_EXTRA" is set, but "wp-config.php" already exists' - echo >&2 ' The contents of this variable will _not_ be inserted into the existing "wp-config.php" file.' - echo >&2 ' (see https://github.com/docker-library/wordpress/issues/333 for more details)' - echo >&2 - fi - - # see http://stackoverflow.com/a/2705678/433558 - sed_escape_lhs() { - echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' - } - sed_escape_rhs() { - echo "$@" | sed -e 's/[\/&]/\\&/g' - } - php_escape() { - local escaped="$(php -r 'var_export(('"$2"') $argv[1]);' -- "$1")" - if [ "$2" = 'string' ] && [ "${escaped:0:1}" = "'" ]; then - escaped="${escaped//$'\n'/"' + \"\\n\" + '"}" - fi - echo "$escaped" - } - set_config() { - key="$1" - value="$2" - var_type="${3:-string}" - start="(['\"])$(sed_escape_lhs "$key")\2\s*," - end="\);" - if [ "${key:0:1}" = '$' ]; then - start="^(\s*)$(sed_escape_lhs "$key")\s*=" - end=";" - fi - sed -ri -e "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php - } - - set_config 'DB_HOST' "$WORDPRESS_DB_HOST" - set_config 'DB_USER' "$WORDPRESS_DB_USER" - set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD" - set_config 'DB_NAME' "$WORDPRESS_DB_NAME" - set_config 'DB_CHARSET' "$WORDPRESS_DB_CHARSET" - set_config 'DB_COLLATE' "$WORDPRESS_DB_COLLATE" - - for unique in "${uniqueEnvs[@]}"; do - uniqVar="WORDPRESS_$unique" - if [ -n "${!uniqVar}" ]; then - set_config "$unique" "${!uniqVar}" - else - # if not specified, let's generate a random value - currentVal="$(sed -rn -e "s/define\(\s*(([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\s*\);/\4/p" wp-config.php)" - if [ "$currentVal" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" - fi + { print } + ' "$wpConfigDocker" > wp-config.php + break fi done - - if [ "$WORDPRESS_TABLE_PREFIX" ]; then - set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX" - fi - - if [ "$WORDPRESS_DEBUG" ]; then - set_config 'WP_DEBUG' 1 boolean - fi - - if ! TERM=dumb php -- <<'EOPHP' -connect_error) { - fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n"); - --$maxTries; - if ($maxTries <= 0) { - exit(1); - } - sleep(3); - } -} while ($mysql->connect_error); - -if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($dbName) . '`')) { - fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n"); - $mysql->close(); - exit(1); -} - -$mysql->close(); -EOPHP - then - echo >&2 - echo >&2 "WARNING: unable to establish a database connection to '$WORDPRESS_DB_HOST'" - echo >&2 ' continuing anyways (which might have unexpected results)' - echo >&2 - fi fi - - # now that we're definitely done writing configuration, let's clear out the relevant envrionment variables (so that stray "phpinfo()" calls don't leak secrets from our code) - for e in "${envs[@]}"; do - unset "$e" - done fi exec "$@" diff --git a/beta/php7.3/apache/wp-config-docker.php b/beta/php7.3/apache/wp-config-docker.php new file mode 100644 index 0000000000..5a43e8e641 --- /dev/null +++ b/beta/php7.3/apache/wp-config-docker.php @@ -0,0 +1,120 @@ +&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then - if [ "$(id -u)" = '0' ]; then +if [[ "$1" == apache2* ]] || [ "$1" = 'php-fpm' ]; then + uid="$(id -u)" + gid="$(id -g)" + if [ "$uid" = '0' ]; then case "$1" in apache2*) user="${APACHE_RUN_USER:-www-data}" @@ -41,13 +21,13 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then ;; esac else - user="$(id -u)" - group="$(id -g)" + user="$uid" + group="$gid" fi if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then # if the directory exists and WordPress doesn't appear to be installed AND the permissions of it are root:root, let's chown it (likely a Docker-created directory) - if [ "$(id -u)" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then + if [ "$uid" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then chown "$user:$group" . fi @@ -65,7 +45,7 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then --extract --file - ) - if [ "$user" != '0' ]; then + if [ "$uid" != '0' ]; then # avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted" targetTarArgs+=( --no-overwrite-dir ) fi @@ -84,202 +64,28 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then echo >&2 "Complete! WordPress has been successfully copied to $PWD" fi - # allow any of these "Authentication Unique Keys and Salts." to be specified via - # environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY") - uniqueEnvs=( - AUTH_KEY - SECURE_AUTH_KEY - LOGGED_IN_KEY - NONCE_KEY - AUTH_SALT - SECURE_AUTH_SALT - LOGGED_IN_SALT - NONCE_SALT - ) - envs=( - WORDPRESS_DB_HOST - WORDPRESS_DB_USER - WORDPRESS_DB_PASSWORD - WORDPRESS_DB_NAME - WORDPRESS_DB_CHARSET - WORDPRESS_DB_COLLATE - "${uniqueEnvs[@]/#/WORDPRESS_}" - WORDPRESS_TABLE_PREFIX - WORDPRESS_DEBUG - WORDPRESS_CONFIG_EXTRA - ) - haveConfig= - for e in "${envs[@]}"; do - file_env "$e" - if [ -z "$haveConfig" ] && [ -n "${!e}" ]; then - haveConfig=1 - fi - done - - # linking backwards-compatibility - if [ -n "${!MYSQL_ENV_MYSQL_*}" ]; then - haveConfig=1 - # host defaults to "mysql" below if unspecified - : "${WORDPRESS_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}}" - if [ "$WORDPRESS_DB_USER" = 'root' ]; then - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" - else - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_PASSWORD:-}}" - fi - : "${WORDPRESS_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-}}" - fi - - # only touch "wp-config.php" if we have environment-supplied configuration values - if [ "$haveConfig" ]; then - : "${WORDPRESS_DB_HOST:=mysql}" - : "${WORDPRESS_DB_USER:=root}" - : "${WORDPRESS_DB_PASSWORD:=}" - : "${WORDPRESS_DB_NAME:=wordpress}" - : "${WORDPRESS_DB_CHARSET:=utf8}" - : "${WORDPRESS_DB_COLLATE:=}" - - # version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks - # https://github.com/docker-library/wordpress/issues/116 - # https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4 - sed -ri -e 's/\r$//' wp-config* - - if [ ! -e wp-config.php ]; then - awk ' - /^\/\*.*stop editing.*\*\/$/ && c == 0 { - c = 1 - system("cat") - if (ENVIRON["WORDPRESS_CONFIG_EXTRA"]) { - print "// WORDPRESS_CONFIG_EXTRA" - print ENVIRON["WORDPRESS_CONFIG_EXTRA"] "\n" + wpEnvs=( "${!WORDPRESS_@}" ) + if [ ! -s wp-config.php ] && [ "${#wpEnvs[@]}" -gt 0 ]; then + for wpConfigDocker in \ + wp-config-docker.php \ + /usr/src/wordpress/wp-config-docker.php \ + ; do + if [ -s "$wpConfigDocker" ]; then + echo >&2 "No 'wp-config.php' found in $PWD, but 'WORDPRESS_...' variables supplied; copying '$wpConfigDocker' (${wpEnvs[*]})" + # using "awk" to replace all instances of "put your unique phrase here" with a properly unique string (for AUTH_KEY and friends to have safe defaults if they aren't specified with environment variables) + awk ' + /put your unique phrase here/ { + cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1" + cmd | getline str + close(cmd) + gsub("put your unique phrase here", str) } - } - { print } - ' wp-config-sample.php > wp-config.php <<'EOPHP' -// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact -// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy -if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { - $_SERVER['HTTPS'] = 'on'; -} - -EOPHP - chown "$user:$group" wp-config.php - elif [ -e wp-config.php ] && [ -n "$WORDPRESS_CONFIG_EXTRA" ] && [[ "$(< wp-config.php)" != *"$WORDPRESS_CONFIG_EXTRA"* ]]; then - # (if the config file already contains the requested PHP code, don't print a warning) - echo >&2 - echo >&2 'WARNING: environment variable "WORDPRESS_CONFIG_EXTRA" is set, but "wp-config.php" already exists' - echo >&2 ' The contents of this variable will _not_ be inserted into the existing "wp-config.php" file.' - echo >&2 ' (see https://github.com/docker-library/wordpress/issues/333 for more details)' - echo >&2 - fi - - # see http://stackoverflow.com/a/2705678/433558 - sed_escape_lhs() { - echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' - } - sed_escape_rhs() { - echo "$@" | sed -e 's/[\/&]/\\&/g' - } - php_escape() { - local escaped="$(php -r 'var_export(('"$2"') $argv[1]);' -- "$1")" - if [ "$2" = 'string' ] && [ "${escaped:0:1}" = "'" ]; then - escaped="${escaped//$'\n'/"' + \"\\n\" + '"}" - fi - echo "$escaped" - } - set_config() { - key="$1" - value="$2" - var_type="${3:-string}" - start="(['\"])$(sed_escape_lhs "$key")\2\s*," - end="\);" - if [ "${key:0:1}" = '$' ]; then - start="^(\s*)$(sed_escape_lhs "$key")\s*=" - end=";" - fi - sed -ri -e "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php - } - - set_config 'DB_HOST' "$WORDPRESS_DB_HOST" - set_config 'DB_USER' "$WORDPRESS_DB_USER" - set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD" - set_config 'DB_NAME' "$WORDPRESS_DB_NAME" - set_config 'DB_CHARSET' "$WORDPRESS_DB_CHARSET" - set_config 'DB_COLLATE' "$WORDPRESS_DB_COLLATE" - - for unique in "${uniqueEnvs[@]}"; do - uniqVar="WORDPRESS_$unique" - if [ -n "${!uniqVar}" ]; then - set_config "$unique" "${!uniqVar}" - else - # if not specified, let's generate a random value - currentVal="$(sed -rn -e "s/define\(\s*(([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\s*\);/\4/p" wp-config.php)" - if [ "$currentVal" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" - fi + { print } + ' "$wpConfigDocker" > wp-config.php + break fi done - - if [ "$WORDPRESS_TABLE_PREFIX" ]; then - set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX" - fi - - if [ "$WORDPRESS_DEBUG" ]; then - set_config 'WP_DEBUG' 1 boolean - fi - - if ! TERM=dumb php -- <<'EOPHP' -connect_error) { - fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n"); - --$maxTries; - if ($maxTries <= 0) { - exit(1); - } - sleep(3); - } -} while ($mysql->connect_error); - -if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($dbName) . '`')) { - fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n"); - $mysql->close(); - exit(1); -} - -$mysql->close(); -EOPHP - then - echo >&2 - echo >&2 "WARNING: unable to establish a database connection to '$WORDPRESS_DB_HOST'" - echo >&2 ' continuing anyways (which might have unexpected results)' - echo >&2 - fi fi - - # now that we're definitely done writing configuration, let's clear out the relevant envrionment variables (so that stray "phpinfo()" calls don't leak secrets from our code) - for e in "${envs[@]}"; do - unset "$e" - done fi exec "$@" diff --git a/beta/php7.3/fpm-alpine/wp-config-docker.php b/beta/php7.3/fpm-alpine/wp-config-docker.php new file mode 100644 index 0000000000..5a43e8e641 --- /dev/null +++ b/beta/php7.3/fpm-alpine/wp-config-docker.php @@ -0,0 +1,120 @@ +&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then - if [ "$(id -u)" = '0' ]; then +if [[ "$1" == apache2* ]] || [ "$1" = 'php-fpm' ]; then + uid="$(id -u)" + gid="$(id -g)" + if [ "$uid" = '0' ]; then case "$1" in apache2*) user="${APACHE_RUN_USER:-www-data}" @@ -41,13 +21,13 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then ;; esac else - user="$(id -u)" - group="$(id -g)" + user="$uid" + group="$gid" fi if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then # if the directory exists and WordPress doesn't appear to be installed AND the permissions of it are root:root, let's chown it (likely a Docker-created directory) - if [ "$(id -u)" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then + if [ "$uid" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then chown "$user:$group" . fi @@ -65,7 +45,7 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then --extract --file - ) - if [ "$user" != '0' ]; then + if [ "$uid" != '0' ]; then # avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted" targetTarArgs+=( --no-overwrite-dir ) fi @@ -84,202 +64,28 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then echo >&2 "Complete! WordPress has been successfully copied to $PWD" fi - # allow any of these "Authentication Unique Keys and Salts." to be specified via - # environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY") - uniqueEnvs=( - AUTH_KEY - SECURE_AUTH_KEY - LOGGED_IN_KEY - NONCE_KEY - AUTH_SALT - SECURE_AUTH_SALT - LOGGED_IN_SALT - NONCE_SALT - ) - envs=( - WORDPRESS_DB_HOST - WORDPRESS_DB_USER - WORDPRESS_DB_PASSWORD - WORDPRESS_DB_NAME - WORDPRESS_DB_CHARSET - WORDPRESS_DB_COLLATE - "${uniqueEnvs[@]/#/WORDPRESS_}" - WORDPRESS_TABLE_PREFIX - WORDPRESS_DEBUG - WORDPRESS_CONFIG_EXTRA - ) - haveConfig= - for e in "${envs[@]}"; do - file_env "$e" - if [ -z "$haveConfig" ] && [ -n "${!e}" ]; then - haveConfig=1 - fi - done - - # linking backwards-compatibility - if [ -n "${!MYSQL_ENV_MYSQL_*}" ]; then - haveConfig=1 - # host defaults to "mysql" below if unspecified - : "${WORDPRESS_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}}" - if [ "$WORDPRESS_DB_USER" = 'root' ]; then - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" - else - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_PASSWORD:-}}" - fi - : "${WORDPRESS_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-}}" - fi - - # only touch "wp-config.php" if we have environment-supplied configuration values - if [ "$haveConfig" ]; then - : "${WORDPRESS_DB_HOST:=mysql}" - : "${WORDPRESS_DB_USER:=root}" - : "${WORDPRESS_DB_PASSWORD:=}" - : "${WORDPRESS_DB_NAME:=wordpress}" - : "${WORDPRESS_DB_CHARSET:=utf8}" - : "${WORDPRESS_DB_COLLATE:=}" - - # version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks - # https://github.com/docker-library/wordpress/issues/116 - # https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4 - sed -ri -e 's/\r$//' wp-config* - - if [ ! -e wp-config.php ]; then - awk ' - /^\/\*.*stop editing.*\*\/$/ && c == 0 { - c = 1 - system("cat") - if (ENVIRON["WORDPRESS_CONFIG_EXTRA"]) { - print "// WORDPRESS_CONFIG_EXTRA" - print ENVIRON["WORDPRESS_CONFIG_EXTRA"] "\n" + wpEnvs=( "${!WORDPRESS_@}" ) + if [ ! -s wp-config.php ] && [ "${#wpEnvs[@]}" -gt 0 ]; then + for wpConfigDocker in \ + wp-config-docker.php \ + /usr/src/wordpress/wp-config-docker.php \ + ; do + if [ -s "$wpConfigDocker" ]; then + echo >&2 "No 'wp-config.php' found in $PWD, but 'WORDPRESS_...' variables supplied; copying '$wpConfigDocker' (${wpEnvs[*]})" + # using "awk" to replace all instances of "put your unique phrase here" with a properly unique string (for AUTH_KEY and friends to have safe defaults if they aren't specified with environment variables) + awk ' + /put your unique phrase here/ { + cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1" + cmd | getline str + close(cmd) + gsub("put your unique phrase here", str) } - } - { print } - ' wp-config-sample.php > wp-config.php <<'EOPHP' -// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact -// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy -if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { - $_SERVER['HTTPS'] = 'on'; -} - -EOPHP - chown "$user:$group" wp-config.php - elif [ -e wp-config.php ] && [ -n "$WORDPRESS_CONFIG_EXTRA" ] && [[ "$(< wp-config.php)" != *"$WORDPRESS_CONFIG_EXTRA"* ]]; then - # (if the config file already contains the requested PHP code, don't print a warning) - echo >&2 - echo >&2 'WARNING: environment variable "WORDPRESS_CONFIG_EXTRA" is set, but "wp-config.php" already exists' - echo >&2 ' The contents of this variable will _not_ be inserted into the existing "wp-config.php" file.' - echo >&2 ' (see https://github.com/docker-library/wordpress/issues/333 for more details)' - echo >&2 - fi - - # see http://stackoverflow.com/a/2705678/433558 - sed_escape_lhs() { - echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' - } - sed_escape_rhs() { - echo "$@" | sed -e 's/[\/&]/\\&/g' - } - php_escape() { - local escaped="$(php -r 'var_export(('"$2"') $argv[1]);' -- "$1")" - if [ "$2" = 'string' ] && [ "${escaped:0:1}" = "'" ]; then - escaped="${escaped//$'\n'/"' + \"\\n\" + '"}" - fi - echo "$escaped" - } - set_config() { - key="$1" - value="$2" - var_type="${3:-string}" - start="(['\"])$(sed_escape_lhs "$key")\2\s*," - end="\);" - if [ "${key:0:1}" = '$' ]; then - start="^(\s*)$(sed_escape_lhs "$key")\s*=" - end=";" - fi - sed -ri -e "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php - } - - set_config 'DB_HOST' "$WORDPRESS_DB_HOST" - set_config 'DB_USER' "$WORDPRESS_DB_USER" - set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD" - set_config 'DB_NAME' "$WORDPRESS_DB_NAME" - set_config 'DB_CHARSET' "$WORDPRESS_DB_CHARSET" - set_config 'DB_COLLATE' "$WORDPRESS_DB_COLLATE" - - for unique in "${uniqueEnvs[@]}"; do - uniqVar="WORDPRESS_$unique" - if [ -n "${!uniqVar}" ]; then - set_config "$unique" "${!uniqVar}" - else - # if not specified, let's generate a random value - currentVal="$(sed -rn -e "s/define\(\s*(([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\s*\);/\4/p" wp-config.php)" - if [ "$currentVal" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" - fi + { print } + ' "$wpConfigDocker" > wp-config.php + break fi done - - if [ "$WORDPRESS_TABLE_PREFIX" ]; then - set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX" - fi - - if [ "$WORDPRESS_DEBUG" ]; then - set_config 'WP_DEBUG' 1 boolean - fi - - if ! TERM=dumb php -- <<'EOPHP' -connect_error) { - fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n"); - --$maxTries; - if ($maxTries <= 0) { - exit(1); - } - sleep(3); - } -} while ($mysql->connect_error); - -if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($dbName) . '`')) { - fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n"); - $mysql->close(); - exit(1); -} - -$mysql->close(); -EOPHP - then - echo >&2 - echo >&2 "WARNING: unable to establish a database connection to '$WORDPRESS_DB_HOST'" - echo >&2 ' continuing anyways (which might have unexpected results)' - echo >&2 - fi fi - - # now that we're definitely done writing configuration, let's clear out the relevant envrionment variables (so that stray "phpinfo()" calls don't leak secrets from our code) - for e in "${envs[@]}"; do - unset "$e" - done fi exec "$@" diff --git a/beta/php7.3/fpm/wp-config-docker.php b/beta/php7.3/fpm/wp-config-docker.php new file mode 100644 index 0000000000..5a43e8e641 --- /dev/null +++ b/beta/php7.3/fpm/wp-config-docker.php @@ -0,0 +1,120 @@ +&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then - if [ "$(id -u)" = '0' ]; then +if [[ "$1" == apache2* ]] || [ "$1" = 'php-fpm' ]; then + uid="$(id -u)" + gid="$(id -g)" + if [ "$uid" = '0' ]; then case "$1" in apache2*) user="${APACHE_RUN_USER:-www-data}" @@ -41,13 +21,13 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then ;; esac else - user="$(id -u)" - group="$(id -g)" + user="$uid" + group="$gid" fi if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then # if the directory exists and WordPress doesn't appear to be installed AND the permissions of it are root:root, let's chown it (likely a Docker-created directory) - if [ "$(id -u)" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then + if [ "$uid" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then chown "$user:$group" . fi @@ -65,7 +45,7 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then --extract --file - ) - if [ "$user" != '0' ]; then + if [ "$uid" != '0' ]; then # avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted" targetTarArgs+=( --no-overwrite-dir ) fi @@ -84,202 +64,28 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then echo >&2 "Complete! WordPress has been successfully copied to $PWD" fi - # allow any of these "Authentication Unique Keys and Salts." to be specified via - # environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY") - uniqueEnvs=( - AUTH_KEY - SECURE_AUTH_KEY - LOGGED_IN_KEY - NONCE_KEY - AUTH_SALT - SECURE_AUTH_SALT - LOGGED_IN_SALT - NONCE_SALT - ) - envs=( - WORDPRESS_DB_HOST - WORDPRESS_DB_USER - WORDPRESS_DB_PASSWORD - WORDPRESS_DB_NAME - WORDPRESS_DB_CHARSET - WORDPRESS_DB_COLLATE - "${uniqueEnvs[@]/#/WORDPRESS_}" - WORDPRESS_TABLE_PREFIX - WORDPRESS_DEBUG - WORDPRESS_CONFIG_EXTRA - ) - haveConfig= - for e in "${envs[@]}"; do - file_env "$e" - if [ -z "$haveConfig" ] && [ -n "${!e}" ]; then - haveConfig=1 - fi - done - - # linking backwards-compatibility - if [ -n "${!MYSQL_ENV_MYSQL_*}" ]; then - haveConfig=1 - # host defaults to "mysql" below if unspecified - : "${WORDPRESS_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}}" - if [ "$WORDPRESS_DB_USER" = 'root' ]; then - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" - else - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_PASSWORD:-}}" - fi - : "${WORDPRESS_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-}}" - fi - - # only touch "wp-config.php" if we have environment-supplied configuration values - if [ "$haveConfig" ]; then - : "${WORDPRESS_DB_HOST:=mysql}" - : "${WORDPRESS_DB_USER:=root}" - : "${WORDPRESS_DB_PASSWORD:=}" - : "${WORDPRESS_DB_NAME:=wordpress}" - : "${WORDPRESS_DB_CHARSET:=utf8}" - : "${WORDPRESS_DB_COLLATE:=}" - - # version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks - # https://github.com/docker-library/wordpress/issues/116 - # https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4 - sed -ri -e 's/\r$//' wp-config* - - if [ ! -e wp-config.php ]; then - awk ' - /^\/\*.*stop editing.*\*\/$/ && c == 0 { - c = 1 - system("cat") - if (ENVIRON["WORDPRESS_CONFIG_EXTRA"]) { - print "// WORDPRESS_CONFIG_EXTRA" - print ENVIRON["WORDPRESS_CONFIG_EXTRA"] "\n" + wpEnvs=( "${!WORDPRESS_@}" ) + if [ ! -s wp-config.php ] && [ "${#wpEnvs[@]}" -gt 0 ]; then + for wpConfigDocker in \ + wp-config-docker.php \ + /usr/src/wordpress/wp-config-docker.php \ + ; do + if [ -s "$wpConfigDocker" ]; then + echo >&2 "No 'wp-config.php' found in $PWD, but 'WORDPRESS_...' variables supplied; copying '$wpConfigDocker' (${wpEnvs[*]})" + # using "awk" to replace all instances of "put your unique phrase here" with a properly unique string (for AUTH_KEY and friends to have safe defaults if they aren't specified with environment variables) + awk ' + /put your unique phrase here/ { + cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1" + cmd | getline str + close(cmd) + gsub("put your unique phrase here", str) } - } - { print } - ' wp-config-sample.php > wp-config.php <<'EOPHP' -// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact -// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy -if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { - $_SERVER['HTTPS'] = 'on'; -} - -EOPHP - chown "$user:$group" wp-config.php - elif [ -e wp-config.php ] && [ -n "$WORDPRESS_CONFIG_EXTRA" ] && [[ "$(< wp-config.php)" != *"$WORDPRESS_CONFIG_EXTRA"* ]]; then - # (if the config file already contains the requested PHP code, don't print a warning) - echo >&2 - echo >&2 'WARNING: environment variable "WORDPRESS_CONFIG_EXTRA" is set, but "wp-config.php" already exists' - echo >&2 ' The contents of this variable will _not_ be inserted into the existing "wp-config.php" file.' - echo >&2 ' (see https://github.com/docker-library/wordpress/issues/333 for more details)' - echo >&2 - fi - - # see http://stackoverflow.com/a/2705678/433558 - sed_escape_lhs() { - echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' - } - sed_escape_rhs() { - echo "$@" | sed -e 's/[\/&]/\\&/g' - } - php_escape() { - local escaped="$(php -r 'var_export(('"$2"') $argv[1]);' -- "$1")" - if [ "$2" = 'string' ] && [ "${escaped:0:1}" = "'" ]; then - escaped="${escaped//$'\n'/"' + \"\\n\" + '"}" - fi - echo "$escaped" - } - set_config() { - key="$1" - value="$2" - var_type="${3:-string}" - start="(['\"])$(sed_escape_lhs "$key")\2\s*," - end="\);" - if [ "${key:0:1}" = '$' ]; then - start="^(\s*)$(sed_escape_lhs "$key")\s*=" - end=";" - fi - sed -ri -e "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php - } - - set_config 'DB_HOST' "$WORDPRESS_DB_HOST" - set_config 'DB_USER' "$WORDPRESS_DB_USER" - set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD" - set_config 'DB_NAME' "$WORDPRESS_DB_NAME" - set_config 'DB_CHARSET' "$WORDPRESS_DB_CHARSET" - set_config 'DB_COLLATE' "$WORDPRESS_DB_COLLATE" - - for unique in "${uniqueEnvs[@]}"; do - uniqVar="WORDPRESS_$unique" - if [ -n "${!uniqVar}" ]; then - set_config "$unique" "${!uniqVar}" - else - # if not specified, let's generate a random value - currentVal="$(sed -rn -e "s/define\(\s*(([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\s*\);/\4/p" wp-config.php)" - if [ "$currentVal" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" - fi + { print } + ' "$wpConfigDocker" > wp-config.php + break fi done - - if [ "$WORDPRESS_TABLE_PREFIX" ]; then - set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX" - fi - - if [ "$WORDPRESS_DEBUG" ]; then - set_config 'WP_DEBUG' 1 boolean - fi - - if ! TERM=dumb php -- <<'EOPHP' -connect_error) { - fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n"); - --$maxTries; - if ($maxTries <= 0) { - exit(1); - } - sleep(3); - } -} while ($mysql->connect_error); - -if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($dbName) . '`')) { - fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n"); - $mysql->close(); - exit(1); -} - -$mysql->close(); -EOPHP - then - echo >&2 - echo >&2 "WARNING: unable to establish a database connection to '$WORDPRESS_DB_HOST'" - echo >&2 ' continuing anyways (which might have unexpected results)' - echo >&2 - fi fi - - # now that we're definitely done writing configuration, let's clear out the relevant envrionment variables (so that stray "phpinfo()" calls don't leak secrets from our code) - for e in "${envs[@]}"; do - unset "$e" - done fi exec "$@" diff --git a/beta/php7.4/apache/wp-config-docker.php b/beta/php7.4/apache/wp-config-docker.php new file mode 100644 index 0000000000..5a43e8e641 --- /dev/null +++ b/beta/php7.4/apache/wp-config-docker.php @@ -0,0 +1,120 @@ +&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then - if [ "$(id -u)" = '0' ]; then +if [[ "$1" == apache2* ]] || [ "$1" = 'php-fpm' ]; then + uid="$(id -u)" + gid="$(id -g)" + if [ "$uid" = '0' ]; then case "$1" in apache2*) user="${APACHE_RUN_USER:-www-data}" @@ -41,13 +21,13 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then ;; esac else - user="$(id -u)" - group="$(id -g)" + user="$uid" + group="$gid" fi if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then # if the directory exists and WordPress doesn't appear to be installed AND the permissions of it are root:root, let's chown it (likely a Docker-created directory) - if [ "$(id -u)" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then + if [ "$uid" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then chown "$user:$group" . fi @@ -65,7 +45,7 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then --extract --file - ) - if [ "$user" != '0' ]; then + if [ "$uid" != '0' ]; then # avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted" targetTarArgs+=( --no-overwrite-dir ) fi @@ -84,202 +64,28 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then echo >&2 "Complete! WordPress has been successfully copied to $PWD" fi - # allow any of these "Authentication Unique Keys and Salts." to be specified via - # environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY") - uniqueEnvs=( - AUTH_KEY - SECURE_AUTH_KEY - LOGGED_IN_KEY - NONCE_KEY - AUTH_SALT - SECURE_AUTH_SALT - LOGGED_IN_SALT - NONCE_SALT - ) - envs=( - WORDPRESS_DB_HOST - WORDPRESS_DB_USER - WORDPRESS_DB_PASSWORD - WORDPRESS_DB_NAME - WORDPRESS_DB_CHARSET - WORDPRESS_DB_COLLATE - "${uniqueEnvs[@]/#/WORDPRESS_}" - WORDPRESS_TABLE_PREFIX - WORDPRESS_DEBUG - WORDPRESS_CONFIG_EXTRA - ) - haveConfig= - for e in "${envs[@]}"; do - file_env "$e" - if [ -z "$haveConfig" ] && [ -n "${!e}" ]; then - haveConfig=1 - fi - done - - # linking backwards-compatibility - if [ -n "${!MYSQL_ENV_MYSQL_*}" ]; then - haveConfig=1 - # host defaults to "mysql" below if unspecified - : "${WORDPRESS_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}}" - if [ "$WORDPRESS_DB_USER" = 'root' ]; then - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" - else - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_PASSWORD:-}}" - fi - : "${WORDPRESS_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-}}" - fi - - # only touch "wp-config.php" if we have environment-supplied configuration values - if [ "$haveConfig" ]; then - : "${WORDPRESS_DB_HOST:=mysql}" - : "${WORDPRESS_DB_USER:=root}" - : "${WORDPRESS_DB_PASSWORD:=}" - : "${WORDPRESS_DB_NAME:=wordpress}" - : "${WORDPRESS_DB_CHARSET:=utf8}" - : "${WORDPRESS_DB_COLLATE:=}" - - # version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks - # https://github.com/docker-library/wordpress/issues/116 - # https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4 - sed -ri -e 's/\r$//' wp-config* - - if [ ! -e wp-config.php ]; then - awk ' - /^\/\*.*stop editing.*\*\/$/ && c == 0 { - c = 1 - system("cat") - if (ENVIRON["WORDPRESS_CONFIG_EXTRA"]) { - print "// WORDPRESS_CONFIG_EXTRA" - print ENVIRON["WORDPRESS_CONFIG_EXTRA"] "\n" + wpEnvs=( "${!WORDPRESS_@}" ) + if [ ! -s wp-config.php ] && [ "${#wpEnvs[@]}" -gt 0 ]; then + for wpConfigDocker in \ + wp-config-docker.php \ + /usr/src/wordpress/wp-config-docker.php \ + ; do + if [ -s "$wpConfigDocker" ]; then + echo >&2 "No 'wp-config.php' found in $PWD, but 'WORDPRESS_...' variables supplied; copying '$wpConfigDocker' (${wpEnvs[*]})" + # using "awk" to replace all instances of "put your unique phrase here" with a properly unique string (for AUTH_KEY and friends to have safe defaults if they aren't specified with environment variables) + awk ' + /put your unique phrase here/ { + cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1" + cmd | getline str + close(cmd) + gsub("put your unique phrase here", str) } - } - { print } - ' wp-config-sample.php > wp-config.php <<'EOPHP' -// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact -// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy -if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { - $_SERVER['HTTPS'] = 'on'; -} - -EOPHP - chown "$user:$group" wp-config.php - elif [ -e wp-config.php ] && [ -n "$WORDPRESS_CONFIG_EXTRA" ] && [[ "$(< wp-config.php)" != *"$WORDPRESS_CONFIG_EXTRA"* ]]; then - # (if the config file already contains the requested PHP code, don't print a warning) - echo >&2 - echo >&2 'WARNING: environment variable "WORDPRESS_CONFIG_EXTRA" is set, but "wp-config.php" already exists' - echo >&2 ' The contents of this variable will _not_ be inserted into the existing "wp-config.php" file.' - echo >&2 ' (see https://github.com/docker-library/wordpress/issues/333 for more details)' - echo >&2 - fi - - # see http://stackoverflow.com/a/2705678/433558 - sed_escape_lhs() { - echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' - } - sed_escape_rhs() { - echo "$@" | sed -e 's/[\/&]/\\&/g' - } - php_escape() { - local escaped="$(php -r 'var_export(('"$2"') $argv[1]);' -- "$1")" - if [ "$2" = 'string' ] && [ "${escaped:0:1}" = "'" ]; then - escaped="${escaped//$'\n'/"' + \"\\n\" + '"}" - fi - echo "$escaped" - } - set_config() { - key="$1" - value="$2" - var_type="${3:-string}" - start="(['\"])$(sed_escape_lhs "$key")\2\s*," - end="\);" - if [ "${key:0:1}" = '$' ]; then - start="^(\s*)$(sed_escape_lhs "$key")\s*=" - end=";" - fi - sed -ri -e "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php - } - - set_config 'DB_HOST' "$WORDPRESS_DB_HOST" - set_config 'DB_USER' "$WORDPRESS_DB_USER" - set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD" - set_config 'DB_NAME' "$WORDPRESS_DB_NAME" - set_config 'DB_CHARSET' "$WORDPRESS_DB_CHARSET" - set_config 'DB_COLLATE' "$WORDPRESS_DB_COLLATE" - - for unique in "${uniqueEnvs[@]}"; do - uniqVar="WORDPRESS_$unique" - if [ -n "${!uniqVar}" ]; then - set_config "$unique" "${!uniqVar}" - else - # if not specified, let's generate a random value - currentVal="$(sed -rn -e "s/define\(\s*(([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\s*\);/\4/p" wp-config.php)" - if [ "$currentVal" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" - fi + { print } + ' "$wpConfigDocker" > wp-config.php + break fi done - - if [ "$WORDPRESS_TABLE_PREFIX" ]; then - set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX" - fi - - if [ "$WORDPRESS_DEBUG" ]; then - set_config 'WP_DEBUG' 1 boolean - fi - - if ! TERM=dumb php -- <<'EOPHP' -connect_error) { - fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n"); - --$maxTries; - if ($maxTries <= 0) { - exit(1); - } - sleep(3); - } -} while ($mysql->connect_error); - -if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($dbName) . '`')) { - fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n"); - $mysql->close(); - exit(1); -} - -$mysql->close(); -EOPHP - then - echo >&2 - echo >&2 "WARNING: unable to establish a database connection to '$WORDPRESS_DB_HOST'" - echo >&2 ' continuing anyways (which might have unexpected results)' - echo >&2 - fi fi - - # now that we're definitely done writing configuration, let's clear out the relevant envrionment variables (so that stray "phpinfo()" calls don't leak secrets from our code) - for e in "${envs[@]}"; do - unset "$e" - done fi exec "$@" diff --git a/beta/php7.4/fpm-alpine/wp-config-docker.php b/beta/php7.4/fpm-alpine/wp-config-docker.php new file mode 100644 index 0000000000..5a43e8e641 --- /dev/null +++ b/beta/php7.4/fpm-alpine/wp-config-docker.php @@ -0,0 +1,120 @@ +&2 "error: both $var and $fileVar are set (but are exclusive)" - exit 1 - fi - local val="$def" - if [ "${!var:-}" ]; then - val="${!var}" - elif [ "${!fileVar:-}" ]; then - val="$(< "${!fileVar}")" - fi - export "$var"="$val" - unset "$fileVar" -} - -if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then - if [ "$(id -u)" = '0' ]; then +if [[ "$1" == apache2* ]] || [ "$1" = 'php-fpm' ]; then + uid="$(id -u)" + gid="$(id -g)" + if [ "$uid" = '0' ]; then case "$1" in apache2*) user="${APACHE_RUN_USER:-www-data}" @@ -41,13 +21,13 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then ;; esac else - user="$(id -u)" - group="$(id -g)" + user="$uid" + group="$gid" fi if [ ! -e index.php ] && [ ! -e wp-includes/version.php ]; then # if the directory exists and WordPress doesn't appear to be installed AND the permissions of it are root:root, let's chown it (likely a Docker-created directory) - if [ "$(id -u)" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then + if [ "$uid" = '0' ] && [ "$(stat -c '%u:%g' .)" = '0:0' ]; then chown "$user:$group" . fi @@ -65,7 +45,7 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then --extract --file - ) - if [ "$user" != '0' ]; then + if [ "$uid" != '0' ]; then # avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted" targetTarArgs+=( --no-overwrite-dir ) fi @@ -84,202 +64,28 @@ if [[ "$1" == apache2* ]] || [ "$1" == php-fpm ]; then echo >&2 "Complete! WordPress has been successfully copied to $PWD" fi - # allow any of these "Authentication Unique Keys and Salts." to be specified via - # environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY") - uniqueEnvs=( - AUTH_KEY - SECURE_AUTH_KEY - LOGGED_IN_KEY - NONCE_KEY - AUTH_SALT - SECURE_AUTH_SALT - LOGGED_IN_SALT - NONCE_SALT - ) - envs=( - WORDPRESS_DB_HOST - WORDPRESS_DB_USER - WORDPRESS_DB_PASSWORD - WORDPRESS_DB_NAME - WORDPRESS_DB_CHARSET - WORDPRESS_DB_COLLATE - "${uniqueEnvs[@]/#/WORDPRESS_}" - WORDPRESS_TABLE_PREFIX - WORDPRESS_DEBUG - WORDPRESS_CONFIG_EXTRA - ) - haveConfig= - for e in "${envs[@]}"; do - file_env "$e" - if [ -z "$haveConfig" ] && [ -n "${!e}" ]; then - haveConfig=1 - fi - done - - # linking backwards-compatibility - if [ -n "${!MYSQL_ENV_MYSQL_*}" ]; then - haveConfig=1 - # host defaults to "mysql" below if unspecified - : "${WORDPRESS_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}}" - if [ "$WORDPRESS_DB_USER" = 'root' ]; then - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}}" - else - : "${WORDPRESS_DB_PASSWORD:=${MYSQL_ENV_MYSQL_PASSWORD:-}}" - fi - : "${WORDPRESS_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-}}" - fi - - # only touch "wp-config.php" if we have environment-supplied configuration values - if [ "$haveConfig" ]; then - : "${WORDPRESS_DB_HOST:=mysql}" - : "${WORDPRESS_DB_USER:=root}" - : "${WORDPRESS_DB_PASSWORD:=}" - : "${WORDPRESS_DB_NAME:=wordpress}" - : "${WORDPRESS_DB_CHARSET:=utf8}" - : "${WORDPRESS_DB_COLLATE:=}" - - # version 4.4.1 decided to switch to windows line endings, that breaks our seds and awks - # https://github.com/docker-library/wordpress/issues/116 - # https://github.com/WordPress/WordPress/commit/1acedc542fba2482bab88ec70d4bea4b997a92e4 - sed -ri -e 's/\r$//' wp-config* - - if [ ! -e wp-config.php ]; then - awk ' - /^\/\*.*stop editing.*\*\/$/ && c == 0 { - c = 1 - system("cat") - if (ENVIRON["WORDPRESS_CONFIG_EXTRA"]) { - print "// WORDPRESS_CONFIG_EXTRA" - print ENVIRON["WORDPRESS_CONFIG_EXTRA"] "\n" + wpEnvs=( "${!WORDPRESS_@}" ) + if [ ! -s wp-config.php ] && [ "${#wpEnvs[@]}" -gt 0 ]; then + for wpConfigDocker in \ + wp-config-docker.php \ + /usr/src/wordpress/wp-config-docker.php \ + ; do + if [ -s "$wpConfigDocker" ]; then + echo >&2 "No 'wp-config.php' found in $PWD, but 'WORDPRESS_...' variables supplied; copying '$wpConfigDocker' (${wpEnvs[*]})" + # using "awk" to replace all instances of "put your unique phrase here" with a properly unique string (for AUTH_KEY and friends to have safe defaults if they aren't specified with environment variables) + awk ' + /put your unique phrase here/ { + cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1" + cmd | getline str + close(cmd) + gsub("put your unique phrase here", str) } - } - { print } - ' wp-config-sample.php > wp-config.php <<'EOPHP' -// If we're behind a proxy server and using HTTPS, we need to alert WordPress of that fact -// see also http://codex.wordpress.org/Administration_Over_SSL#Using_a_Reverse_Proxy -if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') { - $_SERVER['HTTPS'] = 'on'; -} - -EOPHP - chown "$user:$group" wp-config.php - elif [ -e wp-config.php ] && [ -n "$WORDPRESS_CONFIG_EXTRA" ] && [[ "$(< wp-config.php)" != *"$WORDPRESS_CONFIG_EXTRA"* ]]; then - # (if the config file already contains the requested PHP code, don't print a warning) - echo >&2 - echo >&2 'WARNING: environment variable "WORDPRESS_CONFIG_EXTRA" is set, but "wp-config.php" already exists' - echo >&2 ' The contents of this variable will _not_ be inserted into the existing "wp-config.php" file.' - echo >&2 ' (see https://github.com/docker-library/wordpress/issues/333 for more details)' - echo >&2 - fi - - # see http://stackoverflow.com/a/2705678/433558 - sed_escape_lhs() { - echo "$@" | sed -e 's/[]\/$*.^|[]/\\&/g' - } - sed_escape_rhs() { - echo "$@" | sed -e 's/[\/&]/\\&/g' - } - php_escape() { - local escaped="$(php -r 'var_export(('"$2"') $argv[1]);' -- "$1")" - if [ "$2" = 'string' ] && [ "${escaped:0:1}" = "'" ]; then - escaped="${escaped//$'\n'/"' + \"\\n\" + '"}" - fi - echo "$escaped" - } - set_config() { - key="$1" - value="$2" - var_type="${3:-string}" - start="(['\"])$(sed_escape_lhs "$key")\2\s*," - end="\);" - if [ "${key:0:1}" = '$' ]; then - start="^(\s*)$(sed_escape_lhs "$key")\s*=" - end=";" - fi - sed -ri -e "s/($start\s*).*($end)$/\1$(sed_escape_rhs "$(php_escape "$value" "$var_type")")\3/" wp-config.php - } - - set_config 'DB_HOST' "$WORDPRESS_DB_HOST" - set_config 'DB_USER' "$WORDPRESS_DB_USER" - set_config 'DB_PASSWORD' "$WORDPRESS_DB_PASSWORD" - set_config 'DB_NAME' "$WORDPRESS_DB_NAME" - set_config 'DB_CHARSET' "$WORDPRESS_DB_CHARSET" - set_config 'DB_COLLATE' "$WORDPRESS_DB_COLLATE" - - for unique in "${uniqueEnvs[@]}"; do - uniqVar="WORDPRESS_$unique" - if [ -n "${!uniqVar}" ]; then - set_config "$unique" "${!uniqVar}" - else - # if not specified, let's generate a random value - currentVal="$(sed -rn -e "s/define\(\s*(([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\s*\);/\4/p" wp-config.php)" - if [ "$currentVal" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" - fi + { print } + ' "$wpConfigDocker" > wp-config.php + break fi done - - if [ "$WORDPRESS_TABLE_PREFIX" ]; then - set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX" - fi - - if [ "$WORDPRESS_DEBUG" ]; then - set_config 'WP_DEBUG' 1 boolean - fi - - if ! TERM=dumb php -- <<'EOPHP' -connect_error) { - fwrite($stderr, "\n" . 'MySQL Connection Error: (' . $mysql->connect_errno . ') ' . $mysql->connect_error . "\n"); - --$maxTries; - if ($maxTries <= 0) { - exit(1); - } - sleep(3); - } -} while ($mysql->connect_error); - -if (!$mysql->query('CREATE DATABASE IF NOT EXISTS `' . $mysql->real_escape_string($dbName) . '`')) { - fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n"); - $mysql->close(); - exit(1); -} - -$mysql->close(); -EOPHP - then - echo >&2 - echo >&2 "WARNING: unable to establish a database connection to '$WORDPRESS_DB_HOST'" - echo >&2 ' continuing anyways (which might have unexpected results)' - echo >&2 - fi fi - - # now that we're definitely done writing configuration, let's clear out the relevant envrionment variables (so that stray "phpinfo()" calls don't leak secrets from our code) - for e in "${envs[@]}"; do - unset "$e" - done fi exec "$@" diff --git a/beta/php7.4/fpm/wp-config-docker.php b/beta/php7.4/fpm/wp-config-docker.php new file mode 100644 index 0000000000..5a43e8e641 --- /dev/null +++ b/beta/php7.4/fpm/wp-config-docker.php @@ -0,0 +1,120 @@ +&2 "WordPress not found in $PWD - copying now..." + if [ -n "$(find -mindepth 1 -maxdepth 1 -not -name wp-content)" ]; then + echo >&2 "WARNING: $PWD is not empty! (copying anyhow)" + fi + sourceTarArgs=( + --create + --file - + --directory /usr/src/wordpress + --owner "$user" --group "$group" + ) + targetTarArgs=( + --extract + --file - + ) + if [ "$uid" != '0' ]; then + # avoid "tar: .: Cannot utime: Operation not permitted" and "tar: .: Cannot change mode to rwxr-xr-x: Operation not permitted" + targetTarArgs+=( --no-overwrite-dir ) + fi + # loop over "pluggable" content in the source, and if it already exists in the destination, skip it + # https://github.com/docker-library/wordpress/issues/506 ("wp-content" persisted, "akismet" updated, WordPress container restarted/recreated, "akismet" downgraded) + for contentDir in /usr/src/wordpress/wp-content/*/*/; do + contentDir="${contentDir%/}" + [ -d "$contentDir" ] || continue + contentPath="${contentDir#/usr/src/wordpress/}" # "wp-content/plugins/akismet", etc. + if [ -d "$PWD/$contentPath" ]; then + echo >&2 "WARNING: '$PWD/$contentPath' exists! (not copying the WordPress version)" + sourceTarArgs+=( --exclude "./$contentPath" ) + fi + done + tar "${sourceTarArgs[@]}" . | tar "${targetTarArgs[@]}" + echo >&2 "Complete! WordPress has been successfully copied to $PWD" + fi + + wpEnvs=( "${!WORDPRESS_@}" ) + if [ ! -s wp-config.php ] && [ "${#wpEnvs[@]}" -gt 0 ]; then + for wpConfigDocker in \ + wp-config-docker.php \ + /usr/src/wordpress/wp-config-docker.php \ + ; do + if [ -s "$wpConfigDocker" ]; then + echo >&2 "No 'wp-config.php' found in $PWD, but 'WORDPRESS_...' variables supplied; copying '$wpConfigDocker' (${wpEnvs[*]})" + # using "awk" to replace all instances of "put your unique phrase here" with a properly unique string (for AUTH_KEY and friends to have safe defaults if they aren't specified with environment variables) + awk ' + /put your unique phrase here/ { + cmd = "head -c1m /dev/urandom | sha1sum | cut -d\\ -f1" + cmd | getline str + close(cmd) + gsub("put your unique phrase here", str) + } + { print } + ' "$wpConfigDocker" > wp-config.php + break + fi + done + fi +fi + +exec "$@" diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh index 8ca2c547a4..1d6d1f087c 100755 --- a/generate-stackbrew-library.sh +++ b/generate-stackbrew-library.sh @@ -82,7 +82,7 @@ for version; do if [ "$version" = 'beta' ] && latestVersion="$(jq -r '.latest.version // ""' versions.json)" && [ "$latestVersion" = "$fullVersion" ]; then # "beta" channel even with release, skip it - continue + : #continue # TODO once something newer than 5.6 is released, this should be restored (explicit "beta" for allowing pre-release testing of "wp-config-docker.php") fi versionAliases=() diff --git a/wp-config-docker.php b/wp-config-docker.php new file mode 100644 index 0000000000..5a43e8e641 --- /dev/null +++ b/wp-config-docker.php @@ -0,0 +1,120 @@ +