diff --git a/Dockerfile.template b/Dockerfile.template index 7895b42..faa4007 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -9,18 +9,29 @@ LABEL maintainer="{{ env.joomlaMaintainers }}" # Disable remote database security requirements. ENV JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK=1 {{ if is_alpine then ( -}} -# entrypoint.sh dependencies -RUN apk add --no-cache \ - bash -{{ ) else "" end -}} -{{ if env.variant == "apache" then ( -}} -# Enable Apache Rewrite Module -RUN a2enmod rewrite -{{ ) else "" end -}} -# Install the PHP extensions +RUN set -eux; \ + apk add --no-cache \ +# in theory, docker-entrypoint.sh is POSIX-compliant, but priority is a working, consistent image + bash \ +# Ghostscript is required for rendering PDF previews + ghostscript \ +# Alpine package for "imagemagick" contains ~120 .so files + imagemagick \ + ; +{{ ) else ( -}} +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ +# Ghostscript is required for rendering PDF previews + ghostscript \ + ; \ + rm -rf /var/lib/apt/lists/* +{{ ) end -}} + +# install the PHP extensions we need. RUN set -ex; \ -{{ if is_alpine then ( -}} \ +{{ if is_alpine then ( -}} apk add --no-cache --virtual .build-deps \ $PHPIZE_DEPS \ autoconf \ @@ -29,22 +40,60 @@ RUN set -ex; \ {{ if env.version == "4.1" then ( -}} icu-dev \ {{ ) else "" end -}} + freetype-dev \ + imagemagick-dev \ libjpeg-turbo-dev \ {{ if env.version == "3.10" then ( -}} libmcrypt-dev \ {{ ) else "" end -}} libmemcached-dev \ libpng-dev \ + libwebp-dev \ libzip-dev \ openldap-dev \ pcre-dev \ postgresql-dev \ ; \ +{{ ) else ( -}} + savedAptMark="$(apt-mark showmanual)"; \ \ - docker-php-ext-configure gd --with-jpeg; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + libbz2-dev \ + libgmp-dev \ +{{ if env.version == "4.1" then ( -}} + libicu-dev \ +{{ ) else "" end -}} + libfreetype6-dev \ + libjpeg-dev \ + libldap2-dev \ +{{ if env.version == "3.10" then ( -}} + libmcrypt-dev \ +{{ ) else "" end -}} + libmemcached-dev \ + libmagickwand-dev \ + libpq-dev \ + libpng-dev \ + libwebp-dev \ + libzip-dev \ + ; \ +{{ ) end -}} + \ + docker-php-ext-configure gd \ + --with-freetype \ + --with-jpeg \ + --with-webp \ + ; \ +{{ if is_alpine then ( -}} docker-php-ext-configure ldap; \ +{{ ) else ( -}} + debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \ + docker-php-ext-configure ldap --with-libdir="lib/$debMultiarch"; \ +{{ ) end -}} docker-php-ext-install -j "$(nproc)" \ bz2 \ + bcmath \ + exif \ gd \ gmp \ {{ if env.version == "4.1" then ( -}} @@ -57,6 +106,23 @@ RUN set -ex; \ pgsql \ zip \ ; \ +{{ if is_alpine then ( -}} +# WARNING: imagick is likely not supported on Alpine: https://github.com/Imagick/imagick/issues/328 +{{ ) else "" end -}} +# https://pecl.php.net/package/imagick + pecl install imagick-3.6.0; \ + docker-php-ext-enable imagick; \ + rm -r /tmp/pear; \ + \ +# some misbehaving extensions end up outputting to stdout + out="$(php -r 'exit(0);')"; \ + [ -z "$out" ]; \ + err="$(php -r 'exit(0);' 3>&1 1>&2 2>&3)"; \ + [ -z "$err" ]; \ + \ + extDir="$(php -r 'echo ini_get("extension_dir");')"; \ + [ -d "$extDir" ]; \ +{{ if is_alpine then ( -}} \ # pecl will claim success even if one install fails, so we need to perform each install separately pecl install APCu-{{ env.pecl_APCu }}; \ @@ -77,53 +143,14 @@ RUN set -ex; \ rm -r /tmp/pear; \ \ runDeps="$( \ - scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \ - | tr ',' '\n' \ - | sort -u \ - | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ - )"; \ - apk add --virtual .joomla-phpext-rundeps $runDeps; \ - apk del .build-deps + scanelf --needed --nobanner --format '%n#p' --recursive "$extDir" \ + | tr ',' '\n' \ + | sort -u \ + | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ + )"; \ + apk add --no-network --virtual .joomla-phpexts-rundeps $runDeps; \ + apk del --no-network .build-deps; \ {{ ) else ( -}} - \ - savedAptMark="$(apt-mark showmanual)"; \ - \ - apt-get update; \ - apt-get install -y --no-install-recommends \ - libbz2-dev \ - libgmp-dev \ -{{ if env.version == "4.1" then ( -}} - libicu-dev \ -{{ ) else "" end -}} - libjpeg-dev \ - libldap2-dev \ -{{ if env.version == "3.10" then ( -}} - libmcrypt-dev \ -{{ ) else "" end -}} - libmemcached-dev \ - libpng-dev \ - libpq-dev \ - libzip-dev \ - ; \ - \ - docker-php-ext-configure gd --with-jpeg; \ - debMultiarch="$(dpkg-architecture --query DEB_BUILD_MULTIARCH)"; \ - docker-php-ext-configure ldap --with-libdir="lib/$debMultiarch"; \ - docker-php-ext-install -j "$(nproc)" \ - bz2 \ - gd \ - gmp \ -{{ if env.version == "4.1" then ( -}} - intl \ -{{ ) else "" end -}} - ldap \ - mysqli \ - pdo_mysql \ - pdo_pgsql \ - pgsql \ - zip \ - ; \ - \ # pecl will claim success even if one install fails, so we need to perform each install separately pecl install APCu-{{ env.pecl_APCu }}; \ pecl install memcached-{{ env.pecl_memcached }}; \ @@ -139,7 +166,7 @@ RUN set -ex; \ # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies apt-mark auto '.*' > /dev/null; \ apt-mark manual $savedAptMark; \ - ldd "$(php -r 'echo ini_get("extension_dir");')"/*.so \ + ldd "$extDir"/*.so \ | awk '/=>/ { print $3 }' \ | sort -u \ | xargs -r dpkg-query -S \ @@ -148,8 +175,58 @@ RUN set -ex; \ | xargs -rt apt-mark manual; \ \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*; \ {{ ) end -}} + \ + ! { ldd "$extDir"/*.so | grep 'not found'; }; \ +# check for output like "PHP Warning: PHP Startup: Unable to load dynamic library 'foo' (tried: ...) + err="$(php --version 3>&1 1>&2 2>&3)"; \ + [ -z "$err" ] + +# set recommended PHP.ini settings +# see https://secure.php.net/manual/en/opcache.installation.php +RUN set -eux; \ + docker-php-ext-enable opcache; \ + { \ + 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'; \ + } > /usr/local/etc/php/conf.d/opcache-recommended.ini +# set recommended error logging +RUN { \ +# https://www.php.net/manual/en/errorfunc.constants.php + echo 'error_reporting = E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_RECOVERABLE_ERROR'; \ + echo 'display_errors = Off'; \ + echo 'display_startup_errors = Off'; \ + echo 'log_errors = On'; \ + echo 'error_log = /dev/stderr'; \ + echo 'log_errors_max_len = 1024'; \ + echo 'ignore_repeated_errors = On'; \ + echo 'ignore_repeated_source = Off'; \ + echo 'html_errors = Off'; \ + } > /usr/local/etc/php/conf.d/error-logging.ini +{{ if env.variant == "apache" then ( -}} + +RUN set -eux; \ + a2enmod rewrite expires; \ + \ +# https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html + a2enmod remoteip; \ + { \ + echo 'RemoteIPHeader X-Forwarded-For'; \ +# these IP ranges are reserved for "private" use and should thus *usually* be safe inside Docker + echo 'RemoteIPTrustedProxy 10.0.0.0/8'; \ + echo 'RemoteIPTrustedProxy 172.16.0.0/12'; \ + echo 'RemoteIPTrustedProxy 192.168.0.0/16'; \ + echo 'RemoteIPTrustedProxy 169.254.0.0/16'; \ + echo 'RemoteIPTrustedProxy 127.0.0.0/8'; \ + } > /etc/apache2/conf-available/remoteip.conf; \ + a2enconf remoteip; \ +# (replace all instances of "%h" with "%a" in LogFormat) + find /etc/apache2 -type f -name '*.conf' -exec sed -ri 's/([[:space:]]*LogFormat[[:space:]]+"[^"]*)%h([^"]*")/\1%a\2/g' '{}' + +{{ ) else "" end -}} VOLUME /var/www/html @@ -159,14 +236,14 @@ ENV JOOMLA_SHA512 {{ env.joomlaSha512 }} # Download package and extract to web volume RUN set -ex; \ - curl -o joomla.tar.bz2 -SL https://github.com/joomla/joomla-cms/releases/download/${JOOMLA_VERSION}/Joomla_${JOOMLA_VERSION}-Stable-Full_Package.tar.bz2; \ + curl -o joomla.tar.bz2 -SL {{ env.joomlaPackage }}; \ echo "$JOOMLA_SHA512 *joomla.tar.bz2" | sha512sum -c -; \ mkdir /usr/src/joomla; \ tar -xf joomla.tar.bz2 -C /usr/src/joomla; \ rm joomla.tar.bz2; \ chown -R www-data:www-data /usr/src/joomla -# Copy init scripts and custom .htaccess +# Copy init scripts COPY docker-entrypoint.sh /entrypoint.sh COPY makedb.php /makedb.php @@ -177,4 +254,4 @@ CMD ["apache2-foreground"] CMD ["php-fpm"] {{ ) end -}} -# vim:set ft=dockerfile: + diff --git a/apply-templates.sh b/apply-templates.sh index 40d8b4e..92ff433 100755 --- a/apply-templates.sh +++ b/apply-templates.sh @@ -49,6 +49,9 @@ for version; do # get this version Joomla Sha512 joomlaSha512="$(echo "${joomlaVersionDetails}" | jq -r '.sha512')" export joomlaSha512 + # get this version Joomla Package URL + joomlaPackage="$(echo "${joomlaVersionDetails}" | jq -r '.package')" + export joomlaPackage for phpVersion in "${phpVersions[@]}"; do export phpVersion @@ -89,3 +92,4 @@ for version; do done done done + diff --git a/versions.sh b/versions.sh index 453f2fd..bb49c61 100755 --- a/versions.sh +++ b/versions.sh @@ -39,16 +39,33 @@ for version in "${versions[@]}"; do # lets get the full version fullVersion=$(echo $versionsHelper | jq -r '.[env.version].version') export fullVersion - # get the url version - urlVersion=$(echo $fullVersion | sed -e 's/\./-/g') - # get the hash - sha512="$(curl -fsSL "https://downloads.joomla.org/api/v1/signatures/cms/$urlVersion" | jq -r --arg file "Joomla_${fullVersion}-Stable-Full_Package.tar.bz2" '.[] | .[] | select(.filename == $file).sha512')" + # lets see if we have a tar URL + package=$(echo $versionsHelper | jq -r '.[env.version].package') + + # when not found we load sha512 from API + if [ "${package}" = 'null' ]; then + # get the url version + urlVersion=$(echo $fullVersion | sed -e 's/\./-/g') + # get the hash + sha512="$(curl -fsSL "https://downloads.joomla.org/api/v1/signatures/cms/$urlVersion" | jq -r --arg file "Joomla_${fullVersion}-Stable-Full_Package.tar.bz2" '.[] | .[] | select(.filename == $file).sha512')" + # set the full URL for the IMAGES + package="https://github.com/joomla/joomla-cms/releases/download/${fullVersion}/Joomla_${fullVersion}-Stable-Full_Package.tar.bz2" + else + # we get the sha from the package + curl -o joomla.tar.bz2 -SL "${package}" &>/dev/null + # get the hash + sha512=$(sha512sum joomla.tar.bz2 | cut -d " " -f 1) + # remove the file + rm joomla.tar.bz2 + fi # set the hash to the JSON - if [ -n "$sha512" ]; then + if [ -n "$sha512" ] && [ -n "$package" ]; then export sha512 + export package doc="$(jq <<<"$doc" -c '.sha512 = env.sha512')" + doc="$(jq <<<"$doc" -c '.package = env.package')" fi # get the default php version @@ -92,3 +109,4 @@ done # store the JSON to the file system jq <<<"$json" -S . >versions.json +