diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..425f75d --- /dev/null +++ b/.drone.yml @@ -0,0 +1,74 @@ +matrix: + include: + - PHP_VERSION: 7.2 + TARGET: httpd-php + - PHP_VERSION: 7.2 + TARGET: httpd-php-dev + OCI8_VERSION: 2.1.8 + - PHP_VERSION: 7.2 + OCI8_VERSION: 2.1.8 + TARGET: httpd-php-full + - PHP_VERSION: 7.1 + TARGET: httpd-php + - PHP_VERSION: 7.1 + TARGET: httpd-php-dev + OCI8_VERSION: 2.1.8 + - PHP_VERSION: 7.1 + OCI8_VERSION: 2.1.8 + TARGET: httpd-php-full + - PHP_VERSION: 5.6 + TARGET: httpd-php + - PHP_VERSION: 5.6 + TARGET: httpd-php-dev + OCI8_VERSION: 2.0.12 + - PHP_VERSION: 5.6 + OCI8_VERSION: 2.0.12 + TARGET: httpd-php-full + + +pipeline: + # Build and push release + build-and-push-branch: + image: plugins/docker + repo: fpfis/${TARGET} + tags: ${PHP_VERSION} + secrets: [ DOCKER_USERNAME, DOCKER_PASSWORD ] + target: ${TARGET} + build_args: + - php_version=${PHP_VERSION} + - oci8_version=${OCI8_VERSION} + when: + event: push + branch: develop + + # Mark production + build-and-push-production: + image: plugins/docker + repo: fpfis/${TARGET} + tags: production-${PHP_VERSION} + target: ${TARGET} + secrets: [ DOCKER_USERNAME, DOCKER_PASSWORD ] + build_args: + - php_version=${PHP_VERSION} + - oci8_version=${OCI8_VERSION} + when: + event: push + branch: master + + # Mark production + build-and-push-tag: + image: plugins/docker + repo: fpfis/${TARGET} + tags: + - ${PHP_VERSION} + - ${DRONE_TAG%.*} + - ${DRONE_TAG} + target: ${TARGET} + secrets: [ DOCKER_USERNAME, DOCKER_PASSWORD ] + build_args: + - php_version=${PHP_VERSION} + - oci8_version=${OCI8_VERSION} + when: + event: tag + matrix: + PHP_VERSION: ${DRONE_TAG%.*} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9cd46b8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,60 @@ +## Base PHP image : + +FROM ubuntu as httpd-php + +# Build arguments +ENV DEBIAN_FRONTEND=noninteractive +ARG php_version="5.6" +ARG php_modules="curl soap bz2 calendar exif mysql opcache zip xsl intl mcrypt yaml mbstring ldap sockets iconv gd redis memcached tidy" +ARG apache2_modules="proxy_fcgi setenvif rewrite" +ARG USER_ID=1000 +ARG GROUP_ID=1000 + +# Default configuration and environment +ENV php_version=${php_version} \ + FPM_MAX_CHILDREN=5 \ + FPM_MIN_CHILDREN=2 \ + DAEMON_USER=www-data \ + DAEMON_GROUP=www-data \ + HTTP_PORT=8080 \ + APACHE_ERROR_LOG=/proc/self/fd/2 \ + APACHE_ACCESS_LOG=/proc/self/fd/1 \ + PHP_MAX_EXECUTION_TIME=30 \ + PHP_MAX_INPUT_TIME=30 \ + PHP_MEMORY_LIMIT=512M \ + DOCUMENT_ROOT=/var/www/html + +# Add our setup scripts and run the base one +ADD scripts /scripts +RUN /scripts/install-base.sh + +# Add our specific configuration +ADD supervisor_conf /etc/supervisor/conf.d +ADD apache2_conf /etc/apache2 +ADD php_conf /etc/php/${php_version}/mods-available +ADD phpfpm_conf /etc/php/${php_version}/fpm/pool.d + +# Enable our specific configuration +RUN phpenmod 90-common 95-prod && \ + phpenmod -s cli 95-cli && \ + a2enmod ${apache2_modules} && \ + a2enconf php${php_version}-fpm prod +ENTRYPOINT ["/scripts/run.sh"] + +## Full PHP images ( adds Java, OCI, and other heavy runtime libs ) +FROM httpd-php as httpd-php-full +ARG oci8_version="2.0.12" +ENV oci8_version=${oci8_version} +RUN /scripts/install-full.sh + +## Based on the full image ( adds developement tools ) +FROM httpd-php-full as httpd-php-dev +ARG composer_version="1.7.2" +ARG drush_version="8.1.17" +ENV PATH=${PATH}:/root/.composer/vendor/bin +ENV COMPOSER_ALLOW_SUPERUSER=1 +ENV PHP_MEMORY_LIMIT=2G +RUN /scripts/install-dev.sh && \ + phpdismod 95-prod && \ + phpenmod 95-dev && \ + a2disconf prod diff --git a/README.md b/README.md index 5026a62..471d74d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,17 @@ # httpd-php -Apache + PHP Docker images +Alpine 3.7 + +Apache + PHP 5.6 + +Monit + +Apache Variables: + +`DAEMON_USER` User that will run Apache and PHP. Defaults to www-data +`DAEMON_GROUP` Daemon group. Defaults to www-data +`DOCUMENT_ROOT` Document Root. Defaults to /var/www/html + + +Module list: + + diff --git a/apache2_conf/apache2.conf b/apache2_conf/apache2.conf new file mode 100644 index 0000000..30c11d4 --- /dev/null +++ b/apache2_conf/apache2.conf @@ -0,0 +1,93 @@ +ServerRoot "/etc/apache2" +PidFile /run/apache2.pid +Listen ${HTTP_PORT} + +User ${DAEMON_USER} +Group ${DAEMON_GROUP} + + +ServerAdmin root@localhost + +# Include module configuration: +IncludeOptional mods-enabled/*.load +IncludeOptional mods-enabled/*.conf + + + AllowOverride none + Require all denied + + + +DocumentRoot ${DOCUMENT_ROOT} + + + AllowOverride All + Require all granted + + + + Options Indexes FollowSymLinks + + AllowOverride All + + Require all granted + + + + DirectoryIndex index.html + + + + Require all denied + + +ErrorLog ${APACHE_ERROR_LOG} +TransferLog ${APACHE_ACCESS_LOG} +LogLevel notice + + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined + LogFormat "%h %l %u %t \"%r\" %>s %b" common + + + LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio + + + + + + ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" + + + + AllowOverride None + Options None + Require all granted + + + + TypesConfig /etc/mime.types + + AddType application/x-compress .Z + AddType application/x-gzip .gz .tgz + + AddType text/html .shtml + AddOutputFilter INCLUDES .shtml + + +AddDefaultCharset UTF-8 + + + MIMEMagicFile conf/magic + + + +EnableSendfile on + + +# Include of directories ignores editors' and dpkg's backup files, +# Include generic snippets of statements +IncludeOptional conf-enabled/*.conf + +# Allow to provide files through volumes +IncludeOptional /etc/apache2/conf.d/*.conf diff --git a/apache2_conf/conf-available/prod.conf b/apache2_conf/conf-available/prod.conf new file mode 100644 index 0000000..21a2df3 --- /dev/null +++ b/apache2_conf/conf-available/prod.conf @@ -0,0 +1,2 @@ +ServerTokens Prod +ServerSignature Off \ No newline at end of file diff --git a/php_conf/90-common.ini b/php_conf/90-common.ini new file mode 100644 index 0000000..d6cefb8 --- /dev/null +++ b/php_conf/90-common.ini @@ -0,0 +1,5 @@ +date.timezone = Europe/Brussels +max_execution_time = ${PHP_MAX_EXECUTION_TIME} +max_input_time = ${PHP_MAX_INPUT_TIME} +memory_limit = ${PHP_MEMORY_LIMIT} +log_errors=On \ No newline at end of file diff --git a/php_conf/95-cli.ini b/php_conf/95-cli.ini new file mode 100644 index 0000000..4ed7788 --- /dev/null +++ b/php_conf/95-cli.ini @@ -0,0 +1 @@ +memory_limit = 4G \ No newline at end of file diff --git a/php_conf/95-dev.ini b/php_conf/95-dev.ini new file mode 100644 index 0000000..d7d265b --- /dev/null +++ b/php_conf/95-dev.ini @@ -0,0 +1,3 @@ +expose_php=On +display_errors=On +sendmail_path = /bin/true \ No newline at end of file diff --git a/php_conf/95-prod.ini b/php_conf/95-prod.ini new file mode 100644 index 0000000..a553174 --- /dev/null +++ b/php_conf/95-prod.ini @@ -0,0 +1,2 @@ +expose_php=Off +display_errors=Off \ No newline at end of file diff --git a/phpfpm_conf/www.conf b/phpfpm_conf/www.conf new file mode 100644 index 0000000..e9a799c --- /dev/null +++ b/phpfpm_conf/www.conf @@ -0,0 +1,16 @@ +[www] + +user = ${DAEMON_USER} +group = ${DAEMON_USER} + +listen = /run/php/php${php_version}-fpm.sock +listen.group = ${DAEMON_USER} +listen.owner = ${DAEMON_USER} + +pm = dynamic +pm.max_children = ${FPM_MAX_CHILDREN} +pm.min_spare_servers = ${FPM_MIN_CHILDREN} +pm.max_spare_servers = ${FPM_MAX_CHILDREN} + +access.log = /proc/self/fd/1 +clear_env = no diff --git a/scripts/install-base.sh b/scripts/install-base.sh new file mode 100755 index 0000000..74abaad --- /dev/null +++ b/scripts/install-base.sh @@ -0,0 +1,25 @@ +#!bin/bash +set -e +set -x + +# Fix www-data uid/gid : +usermod -u ${USER_ID} www-data +groupmod -g ${GROUP_ID} www-data + +apt-get update +apt-get install -y software-properties-common +add-apt-repository -y ppa:ondrej/php + +for module in ${php_modules}; do + if [ "${php_version}" == "7.2" ] && [ "${module}" == "mcrypt" ]; then + echo "WARNING: ${module} not supported on 7.2" + continue + fi + modules="php${php_version}-${module} ${modules}" +done + +apt-get install -y supervisor apache2 php${php_version}-fpm ${modules} + +apt-get autoremove software-properties-common -y --purge +apt-get clean +rm -rf /var/lib/apt/lists/* diff --git a/scripts/install-dev.sh b/scripts/install-dev.sh new file mode 100755 index 0000000..8da5cb3 --- /dev/null +++ b/scripts/install-dev.sh @@ -0,0 +1,18 @@ +#!bin/bash +set -e +set -x +apt-get update + +# Install dev packages : +apt-get install -y php${php_version}-xdebug wget unzip patch git + +# Install PHP dev packages : +wget https://github.com/composer/composer/releases/download/${composer_version}/composer.phar -O /usr/bin/composer +wget https://github.com/drush-ops/drush/releases/download/${drush_version}/drush.phar -O /usr/bin/drush +ln -s /usr/bin/composer /usr/local/bin/composer +chmod +x /usr/bin/composer /usr/bin/drush + +apt-get clean +rm -rf /var/lib/apt/lists/* +rm -rf /tmp/* +rm -Rf /root/.composer/cache diff --git a/scripts/install-full.sh b/scripts/install-full.sh new file mode 100755 index 0000000..949cc8f --- /dev/null +++ b/scripts/install-full.sh @@ -0,0 +1,36 @@ +#!bin/bash +set -e +set -x +apt-get update + +# Fix java installation +mkdir -p /usr/share/man/man1 +apt-get install --no-install-recommends -y libaio1 openjdk-8-jre-headless curl unzip mysql-client + +# OCI8 deps : +curl https://repo.ne-dev.eu/deb/instantclient-basic-linux.x64-12.2.0.1.0.zip > /tmp/instantclient-basic-linux.zip +unzip /tmp/instantclient-basic-linux.zip -d /usr/local/ +curl https://repo.ne-dev.eu/deb/instantclient-sdk-linux.x64-12.2.0.1.0.zip > /tmp/instantclient-sdk-linux.zip +unzip /tmp/instantclient-sdk-linux.zip -d /usr/local/ +ln -s /usr/local/instantclient_12_2/libclntsh.so.12.1 /usr/local/instantclient_12_2/libclntsh.so +echo /usr/local/instantclient_12_2 > /etc/ld.so.conf.d/oracle-instantclient.conf && ldconfig + +# OCI8 build : +apt-get install -y php${php_version}-dev +pecl download oci8-${oci8_version} +tar -xzvf oci8-${oci8_version}.tgz +pushd oci8-${oci8_version} +phpize +./configure --with-oci8=instantclient,/usr/local/instantclient_12_2 +make -j$(nproc) +make install +popd +rm -Rf oci8-${oci8_version} oci8-${oci8_version}.tar.gz +echo "extension=oci8.so" > /etc/php/${php_version}/mods-available/oci8.ini +phpenmod oci8 + +# Clean : +apt-get autoremove -y curl unzip php${php_version}-dev --purge +apt-get clean +rm -rf /var/lib/apt/lists/* +rm -rf /tmp/* diff --git a/scripts/run.sh b/scripts/run.sh new file mode 100755 index 0000000..c014bda --- /dev/null +++ b/scripts/run.sh @@ -0,0 +1,25 @@ +#!/bin/sh +set -e + +# Get uid for the current docroot +[ -z "${DOCUMENT_ROOT}" ] && export DOCUMENT_ROOT=/var/www/html + +# Check if docroot or parent exists : +[ -d "${DOCUMENT_ROOT}" ] && export REF_DIR=${DOCUMENT_ROOT} +# Else use its parent +[ -z "${REF_DIR}" ] && export REF_DIR=$(dirname ${DOCUMENT_ROOT}) + +# Get our command to run +export CMD=$@ + +[ ! -d /run/php ] && mkdir /run/php +[ ! -d /run/apache2 ] && mkdir /run/apache2 + + +if [ -z "${CMD}" ]; then + # As root, let daemon handle the rest + supervisord -nc /etc/supervisor/supervisord.conf +else + # TODO : us ref_dir's permissions to use it's UID + exec ${CMD} +fi diff --git a/supervisor_conf/httpd.conf b/supervisor_conf/httpd.conf new file mode 100644 index 0000000..6538f09 --- /dev/null +++ b/supervisor_conf/httpd.conf @@ -0,0 +1,8 @@ +[program:httpd] +command=bash -c 'source /etc/apache2/envvars && exec apache2 -D FOREGROUND' +killasgroup=true +stopasgroup=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 \ No newline at end of file diff --git a/supervisor_conf/php.conf b/supervisor_conf/php.conf new file mode 100644 index 0000000..64d9e3b --- /dev/null +++ b/supervisor_conf/php.conf @@ -0,0 +1,8 @@ +[program:php] +command=bash -c 'php-fpm%(ENV_php_version)s -g /run/php-fpm.pid -OF' +killasgroup=true +stopasgroup=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 \ No newline at end of file