diff --git a/.travis.yml b/.travis.yml index 8b99430218..b95e631934 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,10 @@ services: docker env: - VARIANT=php5.6/apache - VARIANT=php5.6/fpm + - VARIANT=php5.6/fpm-alpine - VARIANT=php7.0/apache - VARIANT=php7.0/fpm + - VARIANT=php7.0/fpm-alpine install: - git clone https://github.com/docker-library/official-images.git ~/official-images diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template new file mode 100644 index 0000000000..25400de7ab --- /dev/null +++ b/Dockerfile-alpine.template @@ -0,0 +1,59 @@ +FROM php:%%PHP_VERSION%%-%%VARIANT%% + +# docker-entrypoint.sh dependencies +RUN apk add --no-cache \ +# in theory, docker-entrypoint.sh is POSIX-compliant, but priority is a working, consistent image + bash \ +# BusyBox sed is not sufficient for some of our sed expressions + sed + +# install the PHP extensions we need +RUN set -ex; \ + \ + apk add --no-cache --virtual .build-deps \ + libjpeg-turbo-dev \ + libpng-dev \ + ; \ + \ + docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ + docker-php-ext-install gd mysqli opcache; \ + \ + runDeps="$( \ + scanelf --needed --nobanner --recursive \ + /usr/local/lib/php/extensions \ + | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ + | sort -u \ + | xargs -r apk info --installed \ + | sort -u \ + )"; \ + apk add --virtual .wordpress-phpexts-rundeps $runDeps; \ + apk del .build-deps + +# set recommended PHP.ini settings +# see https://secure.php.net/manual/en/opcache.installation.php +RUN { \ + echo 'opcache.memory_consumption=128'; \ + echo 'opcache.interned_strings_buffer=8'; \ + echo 'opcache.max_accelerated_files=4000'; \ + echo 'opcache.revalidate_freq=2'; \ + echo 'opcache.fast_shutdown=1'; \ + echo 'opcache.enable_cli=1'; \ + } > /usr/local/etc/php/conf.d/opcache-recommended.ini +%%VARIANT_EXTRAS%% +VOLUME /var/www/html + +ENV WORDPRESS_VERSION %%WORDPRESS_VERSION%% +ENV WORDPRESS_SHA1 %%WORDPRESS_SHA1%% + +RUN set -ex; \ + curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \ + echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \ +# upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress + tar -xzf wordpress.tar.gz -C /usr/src/; \ + rm wordpress.tar.gz; \ + chown -R www-data:www-data /usr/src/wordpress + +COPY docker-entrypoint.sh /usr/local/bin/ + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["%%CMD%%"] diff --git a/Dockerfile.template b/Dockerfile-debian.template similarity index 55% rename from Dockerfile.template rename to Dockerfile-debian.template index 7857b84d4c..2b39553a0f 100644 --- a/Dockerfile.template +++ b/Dockerfile-debian.template @@ -1,9 +1,18 @@ FROM php:%%PHP_VERSION%%-%%VARIANT%% # install the PHP extensions we need -RUN apt-get update && apt-get install -y libpng12-dev libjpeg-dev && rm -rf /var/lib/apt/lists/* \ - && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \ - && docker-php-ext-install gd mysqli opcache +RUN set -ex; \ + \ + apt-get update; \ + apt-get install -y \ + libjpeg-dev \ + libpng12-dev \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ + docker-php-ext-install gd mysqli opcache +# TODO consider removing the *-dev deps and only keeping the necessary lib* packages # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php @@ -21,17 +30,15 @@ VOLUME /var/www/html ENV WORDPRESS_VERSION %%WORDPRESS_VERSION%% ENV WORDPRESS_SHA1 %%WORDPRESS_SHA1%% -RUN set -x \ - && curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz" \ - && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \ +RUN set -ex; \ + curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \ + echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \ # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress - && tar -xzf wordpress.tar.gz -C /usr/src/ \ - && rm wordpress.tar.gz \ - && chown -R www-data:www-data /usr/src/wordpress + tar -xzf wordpress.tar.gz -C /usr/src/; \ + rm wordpress.tar.gz; \ + chown -R www-data:www-data /usr/src/wordpress COPY docker-entrypoint.sh /usr/local/bin/ -RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat -# ENTRYPOINT resets CMD ENTRYPOINT ["docker-entrypoint.sh"] CMD ["%%CMD%%"] diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index b8c8efb686..9ccfc8f309 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -eu +set -euo pipefail # usage: file_env VAR [DEFAULT] # ie: file_env 'XYZ_DB_PASSWORD' 'example' @@ -135,7 +135,7 @@ EOPHP # if not specified, let's generate a random value current_set="$(sed -rn -e "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)" if [ "$current_set" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1M /dev/urandom | sha1sum | cut -d' ' -f1)" + set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" fi fi done diff --git a/generate-stackbrew-library.sh b/generate-stackbrew-library.sh index 69262ec5ce..cf4959a707 100755 --- a/generate-stackbrew-library.sh +++ b/generate-stackbrew-library.sh @@ -48,7 +48,7 @@ join() { } for phpVersion in "${phpVersions[@]}"; do - for variant in apache fpm; do + for variant in apache fpm fpm-alpine; do dir="$phpVersion/$variant" [ -f "$dir/Dockerfile" ] || continue diff --git a/php5.6/apache/Dockerfile b/php5.6/apache/Dockerfile index 73f3cd29b0..6129c73b58 100644 --- a/php5.6/apache/Dockerfile +++ b/php5.6/apache/Dockerfile @@ -1,9 +1,18 @@ FROM php:5.6-apache # install the PHP extensions we need -RUN apt-get update && apt-get install -y libpng12-dev libjpeg-dev && rm -rf /var/lib/apt/lists/* \ - && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \ - && docker-php-ext-install gd mysqli opcache +RUN set -ex; \ + \ + apt-get update; \ + apt-get install -y \ + libjpeg-dev \ + libpng12-dev \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ + docker-php-ext-install gd mysqli opcache +# TODO consider removing the *-dev deps and only keeping the necessary lib* packages # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php @@ -23,17 +32,15 @@ VOLUME /var/www/html ENV WORDPRESS_VERSION 4.7 ENV WORDPRESS_SHA1 1e14144c4db71421dc4ed22f94c3914dfc3b7020 -RUN set -x \ - && curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz" \ - && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \ +RUN set -ex; \ + curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \ + echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \ # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress - && tar -xzf wordpress.tar.gz -C /usr/src/ \ - && rm wordpress.tar.gz \ - && chown -R www-data:www-data /usr/src/wordpress + tar -xzf wordpress.tar.gz -C /usr/src/; \ + rm wordpress.tar.gz; \ + chown -R www-data:www-data /usr/src/wordpress COPY docker-entrypoint.sh /usr/local/bin/ -RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat -# ENTRYPOINT resets CMD ENTRYPOINT ["docker-entrypoint.sh"] CMD ["apache2-foreground"] diff --git a/php5.6/apache/docker-entrypoint.sh b/php5.6/apache/docker-entrypoint.sh index b8c8efb686..9ccfc8f309 100755 --- a/php5.6/apache/docker-entrypoint.sh +++ b/php5.6/apache/docker-entrypoint.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -eu +set -euo pipefail # usage: file_env VAR [DEFAULT] # ie: file_env 'XYZ_DB_PASSWORD' 'example' @@ -135,7 +135,7 @@ EOPHP # if not specified, let's generate a random value current_set="$(sed -rn -e "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)" if [ "$current_set" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1M /dev/urandom | sha1sum | cut -d' ' -f1)" + set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" fi fi done diff --git a/php5.6/fpm-alpine/Dockerfile b/php5.6/fpm-alpine/Dockerfile new file mode 100644 index 0000000000..a9c71c2ced --- /dev/null +++ b/php5.6/fpm-alpine/Dockerfile @@ -0,0 +1,59 @@ +FROM php:5.6-fpm-alpine + +# docker-entrypoint.sh dependencies +RUN apk add --no-cache \ +# in theory, docker-entrypoint.sh is POSIX-compliant, but priority is a working, consistent image + bash \ +# BusyBox sed is not sufficient for some of our sed expressions + sed + +# install the PHP extensions we need +RUN set -ex; \ + \ + apk add --no-cache --virtual .build-deps \ + libjpeg-turbo-dev \ + libpng-dev \ + ; \ + \ + docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ + docker-php-ext-install gd mysqli opcache; \ + \ + runDeps="$( \ + scanelf --needed --nobanner --recursive \ + /usr/local/lib/php/extensions \ + | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ + | sort -u \ + | xargs -r apk info --installed \ + | sort -u \ + )"; \ + apk add --virtual .wordpress-phpexts-rundeps $runDeps; \ + apk del .build-deps + +# set recommended PHP.ini settings +# see https://secure.php.net/manual/en/opcache.installation.php +RUN { \ + echo 'opcache.memory_consumption=128'; \ + echo 'opcache.interned_strings_buffer=8'; \ + echo 'opcache.max_accelerated_files=4000'; \ + echo 'opcache.revalidate_freq=2'; \ + echo 'opcache.fast_shutdown=1'; \ + echo 'opcache.enable_cli=1'; \ + } > /usr/local/etc/php/conf.d/opcache-recommended.ini + +VOLUME /var/www/html + +ENV WORDPRESS_VERSION 4.7 +ENV WORDPRESS_SHA1 1e14144c4db71421dc4ed22f94c3914dfc3b7020 + +RUN set -ex; \ + curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \ + echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \ +# upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress + tar -xzf wordpress.tar.gz -C /usr/src/; \ + rm wordpress.tar.gz; \ + chown -R www-data:www-data /usr/src/wordpress + +COPY docker-entrypoint.sh /usr/local/bin/ + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["php-fpm"] diff --git a/php5.6/fpm-alpine/docker-entrypoint.sh b/php5.6/fpm-alpine/docker-entrypoint.sh new file mode 100755 index 0000000000..9ccfc8f309 --- /dev/null +++ b/php5.6/fpm-alpine/docker-entrypoint.sh @@ -0,0 +1,193 @@ +#!/bin/bash +set -euo 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 + file_env 'WORDPRESS_DB_HOST' 'mysql' + # if we're linked to MySQL and thus have credentials already, let's use them + file_env 'WORDPRESS_DB_USER' "${MYSQL_ENV_MYSQL_USER:-root}" + if [ "$WORDPRESS_DB_USER" = 'root' ]; then + file_env 'WORDPRESS_DB_PASSWORD' "${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}" + else + file_env 'WORDPRESS_DB_PASSWORD' "${MYSQL_ENV_MYSQL_PASSWORD:-}" + fi + file_env 'WORDPRESS_DB_NAME' "${MYSQL_ENV_MYSQL_DATABASE:-wordpress}" + if [ -z "$WORDPRESS_DB_PASSWORD" ]; then + echo >&2 'error: missing required WORDPRESS_DB_PASSWORD environment variable' + echo >&2 ' Did you forget to -e WORDPRESS_DB_PASSWORD=... ?' + echo >&2 + echo >&2 ' (Also of interest might be WORDPRESS_DB_USER and WORDPRESS_DB_NAME.)' + exit 1 + fi + + if ! [ -e index.php -a -e wp-includes/version.php ]; then + echo >&2 "WordPress not found in $(pwd) - copying now..." + if [ "$(ls -A)" ]; then + echo >&2 "WARNING: $(pwd) is not empty - press Ctrl+C now if this is an error!" + ( set -x; ls -A; sleep 10 ) + fi + tar cf - --one-file-system -C /usr/src/wordpress . | tar xf - + echo >&2 "Complete! WordPress has been successfully copied to $(pwd)" + if [ ! -e .htaccess ]; then + # NOTE: The "Indexes" option is disabled in the php:apache base image + cat > .htaccess <<-'EOF' + # BEGIN WordPress + + RewriteEngine On + RewriteBase / + RewriteRule ^index\.php$ - [L] + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule . /index.php [L] + + # END WordPress + EOF + chown www-data:www-data .htaccess + fi + fi + + # TODO handle WordPress upgrades magically in the same way, but only if wp-includes/version.php's $wp_version is less than /usr/src/wordpress/wp-includes/version.php's $wp_version + + # 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\n|\r/\n/g' wp-config* + + if [ ! -e wp-config.php ]; then + awk '/^\/\*.*stop editing.*\*\/$/ && c == 0 { c = 1; system("cat") } { 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 www-data:www-data wp-config.php + 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() { + php -r 'var_export(('$2') $argv[1]);' -- "$1" + } + 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" + + # allow any of these "Authentication Unique Keys and Salts." to be specified via + # environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY") + UNIQUES=( + AUTH_KEY + SECURE_AUTH_KEY + LOGGED_IN_KEY + NONCE_KEY + AUTH_SALT + SECURE_AUTH_SALT + LOGGED_IN_SALT + NONCE_SALT + ) + for unique in "${UNIQUES[@]}"; do + uniqVar="WORDPRESS_$unique" + file_env "$uniqVar" + if [ "${!uniqVar}" ]; then + set_config "$unique" "${!uniqVar}" + else + # if not specified, let's generate a random value + current_set="$(sed -rn -e "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)" + if [ "$current_set" = 'put your unique phrase here' ]; then + set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" + fi + fi + done + + file_env 'WORDPRESS_TABLE_PREFIX' + if [ "$WORDPRESS_TABLE_PREFIX" ]; then + set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX" + fi + + file_env 'WORDPRESS_DEBUG' + if [ "$WORDPRESS_DEBUG" ]; then + set_config 'WP_DEBUG' 1 boolean + fi + + TERM=dumb php -- "$WORDPRESS_DB_HOST" "$WORDPRESS_DB_USER" "$WORDPRESS_DB_PASSWORD" "$WORDPRESS_DB_NAME" <<'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($argv[4]) . '`')) { + fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n"); + $mysql->close(); + exit(1); +} + +$mysql->close(); +EOPHP +fi + +exec "$@" diff --git a/php5.6/fpm/Dockerfile b/php5.6/fpm/Dockerfile index 31d1cd1324..868bb1739f 100644 --- a/php5.6/fpm/Dockerfile +++ b/php5.6/fpm/Dockerfile @@ -1,9 +1,18 @@ FROM php:5.6-fpm # install the PHP extensions we need -RUN apt-get update && apt-get install -y libpng12-dev libjpeg-dev && rm -rf /var/lib/apt/lists/* \ - && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \ - && docker-php-ext-install gd mysqli opcache +RUN set -ex; \ + \ + apt-get update; \ + apt-get install -y \ + libjpeg-dev \ + libpng12-dev \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ + docker-php-ext-install gd mysqli opcache +# TODO consider removing the *-dev deps and only keeping the necessary lib* packages # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php @@ -21,17 +30,15 @@ VOLUME /var/www/html ENV WORDPRESS_VERSION 4.7 ENV WORDPRESS_SHA1 1e14144c4db71421dc4ed22f94c3914dfc3b7020 -RUN set -x \ - && curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz" \ - && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \ +RUN set -ex; \ + curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \ + echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \ # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress - && tar -xzf wordpress.tar.gz -C /usr/src/ \ - && rm wordpress.tar.gz \ - && chown -R www-data:www-data /usr/src/wordpress + tar -xzf wordpress.tar.gz -C /usr/src/; \ + rm wordpress.tar.gz; \ + chown -R www-data:www-data /usr/src/wordpress COPY docker-entrypoint.sh /usr/local/bin/ -RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat -# ENTRYPOINT resets CMD ENTRYPOINT ["docker-entrypoint.sh"] CMD ["php-fpm"] diff --git a/php5.6/fpm/docker-entrypoint.sh b/php5.6/fpm/docker-entrypoint.sh index b8c8efb686..9ccfc8f309 100755 --- a/php5.6/fpm/docker-entrypoint.sh +++ b/php5.6/fpm/docker-entrypoint.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -eu +set -euo pipefail # usage: file_env VAR [DEFAULT] # ie: file_env 'XYZ_DB_PASSWORD' 'example' @@ -135,7 +135,7 @@ EOPHP # if not specified, let's generate a random value current_set="$(sed -rn -e "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)" if [ "$current_set" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1M /dev/urandom | sha1sum | cut -d' ' -f1)" + set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" fi fi done diff --git a/php7.0/apache/Dockerfile b/php7.0/apache/Dockerfile index fbd84197a7..eb157671b1 100644 --- a/php7.0/apache/Dockerfile +++ b/php7.0/apache/Dockerfile @@ -1,9 +1,18 @@ FROM php:7.0-apache # install the PHP extensions we need -RUN apt-get update && apt-get install -y libpng12-dev libjpeg-dev && rm -rf /var/lib/apt/lists/* \ - && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \ - && docker-php-ext-install gd mysqli opcache +RUN set -ex; \ + \ + apt-get update; \ + apt-get install -y \ + libjpeg-dev \ + libpng12-dev \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ + docker-php-ext-install gd mysqli opcache +# TODO consider removing the *-dev deps and only keeping the necessary lib* packages # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php @@ -23,17 +32,15 @@ VOLUME /var/www/html ENV WORDPRESS_VERSION 4.7 ENV WORDPRESS_SHA1 1e14144c4db71421dc4ed22f94c3914dfc3b7020 -RUN set -x \ - && curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz" \ - && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \ +RUN set -ex; \ + curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \ + echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \ # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress - && tar -xzf wordpress.tar.gz -C /usr/src/ \ - && rm wordpress.tar.gz \ - && chown -R www-data:www-data /usr/src/wordpress + tar -xzf wordpress.tar.gz -C /usr/src/; \ + rm wordpress.tar.gz; \ + chown -R www-data:www-data /usr/src/wordpress COPY docker-entrypoint.sh /usr/local/bin/ -RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat -# ENTRYPOINT resets CMD ENTRYPOINT ["docker-entrypoint.sh"] CMD ["apache2-foreground"] diff --git a/php7.0/apache/docker-entrypoint.sh b/php7.0/apache/docker-entrypoint.sh index b8c8efb686..9ccfc8f309 100755 --- a/php7.0/apache/docker-entrypoint.sh +++ b/php7.0/apache/docker-entrypoint.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -eu +set -euo pipefail # usage: file_env VAR [DEFAULT] # ie: file_env 'XYZ_DB_PASSWORD' 'example' @@ -135,7 +135,7 @@ EOPHP # if not specified, let's generate a random value current_set="$(sed -rn -e "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)" if [ "$current_set" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1M /dev/urandom | sha1sum | cut -d' ' -f1)" + set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" fi fi done diff --git a/php7.0/fpm-alpine/Dockerfile b/php7.0/fpm-alpine/Dockerfile new file mode 100644 index 0000000000..ec387cc078 --- /dev/null +++ b/php7.0/fpm-alpine/Dockerfile @@ -0,0 +1,59 @@ +FROM php:7.0-fpm-alpine + +# docker-entrypoint.sh dependencies +RUN apk add --no-cache \ +# in theory, docker-entrypoint.sh is POSIX-compliant, but priority is a working, consistent image + bash \ +# BusyBox sed is not sufficient for some of our sed expressions + sed + +# install the PHP extensions we need +RUN set -ex; \ + \ + apk add --no-cache --virtual .build-deps \ + libjpeg-turbo-dev \ + libpng-dev \ + ; \ + \ + docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ + docker-php-ext-install gd mysqli opcache; \ + \ + runDeps="$( \ + scanelf --needed --nobanner --recursive \ + /usr/local/lib/php/extensions \ + | awk '{ gsub(/,/, "\nso:", $2); print "so:" $2 }' \ + | sort -u \ + | xargs -r apk info --installed \ + | sort -u \ + )"; \ + apk add --virtual .wordpress-phpexts-rundeps $runDeps; \ + apk del .build-deps + +# set recommended PHP.ini settings +# see https://secure.php.net/manual/en/opcache.installation.php +RUN { \ + echo 'opcache.memory_consumption=128'; \ + echo 'opcache.interned_strings_buffer=8'; \ + echo 'opcache.max_accelerated_files=4000'; \ + echo 'opcache.revalidate_freq=2'; \ + echo 'opcache.fast_shutdown=1'; \ + echo 'opcache.enable_cli=1'; \ + } > /usr/local/etc/php/conf.d/opcache-recommended.ini + +VOLUME /var/www/html + +ENV WORDPRESS_VERSION 4.7 +ENV WORDPRESS_SHA1 1e14144c4db71421dc4ed22f94c3914dfc3b7020 + +RUN set -ex; \ + curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \ + echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \ +# upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress + tar -xzf wordpress.tar.gz -C /usr/src/; \ + rm wordpress.tar.gz; \ + chown -R www-data:www-data /usr/src/wordpress + +COPY docker-entrypoint.sh /usr/local/bin/ + +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["php-fpm"] diff --git a/php7.0/fpm-alpine/docker-entrypoint.sh b/php7.0/fpm-alpine/docker-entrypoint.sh new file mode 100755 index 0000000000..9ccfc8f309 --- /dev/null +++ b/php7.0/fpm-alpine/docker-entrypoint.sh @@ -0,0 +1,193 @@ +#!/bin/bash +set -euo 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 + file_env 'WORDPRESS_DB_HOST' 'mysql' + # if we're linked to MySQL and thus have credentials already, let's use them + file_env 'WORDPRESS_DB_USER' "${MYSQL_ENV_MYSQL_USER:-root}" + if [ "$WORDPRESS_DB_USER" = 'root' ]; then + file_env 'WORDPRESS_DB_PASSWORD' "${MYSQL_ENV_MYSQL_ROOT_PASSWORD:-}" + else + file_env 'WORDPRESS_DB_PASSWORD' "${MYSQL_ENV_MYSQL_PASSWORD:-}" + fi + file_env 'WORDPRESS_DB_NAME' "${MYSQL_ENV_MYSQL_DATABASE:-wordpress}" + if [ -z "$WORDPRESS_DB_PASSWORD" ]; then + echo >&2 'error: missing required WORDPRESS_DB_PASSWORD environment variable' + echo >&2 ' Did you forget to -e WORDPRESS_DB_PASSWORD=... ?' + echo >&2 + echo >&2 ' (Also of interest might be WORDPRESS_DB_USER and WORDPRESS_DB_NAME.)' + exit 1 + fi + + if ! [ -e index.php -a -e wp-includes/version.php ]; then + echo >&2 "WordPress not found in $(pwd) - copying now..." + if [ "$(ls -A)" ]; then + echo >&2 "WARNING: $(pwd) is not empty - press Ctrl+C now if this is an error!" + ( set -x; ls -A; sleep 10 ) + fi + tar cf - --one-file-system -C /usr/src/wordpress . | tar xf - + echo >&2 "Complete! WordPress has been successfully copied to $(pwd)" + if [ ! -e .htaccess ]; then + # NOTE: The "Indexes" option is disabled in the php:apache base image + cat > .htaccess <<-'EOF' + # BEGIN WordPress + + RewriteEngine On + RewriteBase / + RewriteRule ^index\.php$ - [L] + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule . /index.php [L] + + # END WordPress + EOF + chown www-data:www-data .htaccess + fi + fi + + # TODO handle WordPress upgrades magically in the same way, but only if wp-includes/version.php's $wp_version is less than /usr/src/wordpress/wp-includes/version.php's $wp_version + + # 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\n|\r/\n/g' wp-config* + + if [ ! -e wp-config.php ]; then + awk '/^\/\*.*stop editing.*\*\/$/ && c == 0 { c = 1; system("cat") } { 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 www-data:www-data wp-config.php + 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() { + php -r 'var_export(('$2') $argv[1]);' -- "$1" + } + 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" + + # allow any of these "Authentication Unique Keys and Salts." to be specified via + # environment variables with a "WORDPRESS_" prefix (ie, "WORDPRESS_AUTH_KEY") + UNIQUES=( + AUTH_KEY + SECURE_AUTH_KEY + LOGGED_IN_KEY + NONCE_KEY + AUTH_SALT + SECURE_AUTH_SALT + LOGGED_IN_SALT + NONCE_SALT + ) + for unique in "${UNIQUES[@]}"; do + uniqVar="WORDPRESS_$unique" + file_env "$uniqVar" + if [ "${!uniqVar}" ]; then + set_config "$unique" "${!uniqVar}" + else + # if not specified, let's generate a random value + current_set="$(sed -rn -e "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)" + if [ "$current_set" = 'put your unique phrase here' ]; then + set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" + fi + fi + done + + file_env 'WORDPRESS_TABLE_PREFIX' + if [ "$WORDPRESS_TABLE_PREFIX" ]; then + set_config '$table_prefix' "$WORDPRESS_TABLE_PREFIX" + fi + + file_env 'WORDPRESS_DEBUG' + if [ "$WORDPRESS_DEBUG" ]; then + set_config 'WP_DEBUG' 1 boolean + fi + + TERM=dumb php -- "$WORDPRESS_DB_HOST" "$WORDPRESS_DB_USER" "$WORDPRESS_DB_PASSWORD" "$WORDPRESS_DB_NAME" <<'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($argv[4]) . '`')) { + fwrite($stderr, "\n" . 'MySQL "CREATE DATABASE" Error: ' . $mysql->error . "\n"); + $mysql->close(); + exit(1); +} + +$mysql->close(); +EOPHP +fi + +exec "$@" diff --git a/php7.0/fpm/Dockerfile b/php7.0/fpm/Dockerfile index 609579c796..88c46fd30a 100644 --- a/php7.0/fpm/Dockerfile +++ b/php7.0/fpm/Dockerfile @@ -1,9 +1,18 @@ FROM php:7.0-fpm # install the PHP extensions we need -RUN apt-get update && apt-get install -y libpng12-dev libjpeg-dev && rm -rf /var/lib/apt/lists/* \ - && docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr \ - && docker-php-ext-install gd mysqli opcache +RUN set -ex; \ + \ + apt-get update; \ + apt-get install -y \ + libjpeg-dev \ + libpng12-dev \ + ; \ + rm -rf /var/lib/apt/lists/*; \ + \ + docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ + docker-php-ext-install gd mysqli opcache +# TODO consider removing the *-dev deps and only keeping the necessary lib* packages # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php @@ -21,17 +30,15 @@ VOLUME /var/www/html ENV WORDPRESS_VERSION 4.7 ENV WORDPRESS_SHA1 1e14144c4db71421dc4ed22f94c3914dfc3b7020 -RUN set -x \ - && curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz" \ - && echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c - \ +RUN set -ex; \ + curl -o wordpress.tar.gz -fSL "https://wordpress.org/wordpress-${WORDPRESS_VERSION}.tar.gz"; \ + echo "$WORDPRESS_SHA1 *wordpress.tar.gz" | sha1sum -c -; \ # upstream tarballs include ./wordpress/ so this gives us /usr/src/wordpress - && tar -xzf wordpress.tar.gz -C /usr/src/ \ - && rm wordpress.tar.gz \ - && chown -R www-data:www-data /usr/src/wordpress + tar -xzf wordpress.tar.gz -C /usr/src/; \ + rm wordpress.tar.gz; \ + chown -R www-data:www-data /usr/src/wordpress COPY docker-entrypoint.sh /usr/local/bin/ -RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat -# ENTRYPOINT resets CMD ENTRYPOINT ["docker-entrypoint.sh"] CMD ["php-fpm"] diff --git a/php7.0/fpm/docker-entrypoint.sh b/php7.0/fpm/docker-entrypoint.sh index b8c8efb686..9ccfc8f309 100755 --- a/php7.0/fpm/docker-entrypoint.sh +++ b/php7.0/fpm/docker-entrypoint.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -eu +set -euo pipefail # usage: file_env VAR [DEFAULT] # ie: file_env 'XYZ_DB_PASSWORD' 'example' @@ -135,7 +135,7 @@ EOPHP # if not specified, let's generate a random value current_set="$(sed -rn -e "s/define\((([\'\"])$unique\2\s*,\s*)(['\"])(.*)\3\);/\4/p" wp-config.php)" if [ "$current_set" = 'put your unique phrase here' ]; then - set_config "$unique" "$(head -c1M /dev/urandom | sha1sum | cut -d' ' -f1)" + set_config "$unique" "$(head -c1m /dev/urandom | sha1sum | cut -d' ' -f1)" fi fi done diff --git a/update.sh b/update.sh index ed8fc58eaf..a08e1b434f 100755 --- a/update.sh +++ b/update.sh @@ -15,10 +15,17 @@ sha1="$(curl -fsSL "https://wordpress.org/wordpress-$current.tar.gz.sha1")" declare -A variantExtras=( [apache]='\nRUN a2enmod rewrite expires\n' [fpm]='' + [fpm-alpine]='' ) declare -A variantCmds=( [apache]='apache2-foreground' [fpm]='php-fpm' + [fpm-alpine]='php-fpm' +) +declare -A variantBases=( + [apache]='debian' + [fpm]='debian' + [fpm-alpine]='alpine' ) travisEnv= @@ -26,12 +33,13 @@ for phpVersion in "${phpVersions[@]}"; do phpVersionDir="$phpVersion" phpVersion="${phpVersion#php}" - for variant in apache fpm; do + for variant in apache fpm fpm-alpine; do dir="$phpVersionDir/$variant" mkdir -p "$dir" extras="${variantExtras[$variant]}" cmd="${variantCmds[$variant]}" + base="${variantBases[$variant]}" ( set -x @@ -43,7 +51,7 @@ for phpVersion in "${phpVersions[@]}"; do -e 's!%%VARIANT%%!'"$variant"'!g' \ -e 's!%%VARIANT_EXTRAS%%!'"$extras"'!g' \ -e 's!%%CMD%%!'"$cmd"'!g' \ - Dockerfile.template > "$dir/Dockerfile" + "Dockerfile-${base}.template" > "$dir/Dockerfile" cp docker-entrypoint.sh "$dir/docker-entrypoint.sh" )