diff --git a/.gitea/workflows/build_docker.yaml b/.gitea/workflows/build_docker.yaml index 2d73c58..625a736 100644 --- a/.gitea/workflows/build_docker.yaml +++ b/.gitea/workflows/build_docker.yaml @@ -2,7 +2,7 @@ name: Create Docker Image run-name: ${{ gitea.actor }} Building Docker Image 🐳 on: [push] env: - VERSION: 8.3-fpm + VERSION: 8.4 DOCKER_HOST: tcp://127.0.0.1:2375 jobs: diff --git a/docker/Dockerfile b/docker/Dockerfile index 365704f..fdf3183 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,69 +1,47 @@ # NAME docker/php -# VERSION 8.3-fpm-alpine +# VERSION 8.4-fpm-alpine -FROM php:8.3-fpm-alpine +FROM dunglas/frankenphp:php8.4-alpine # Change to http respositories, so they we can cache the install packages RUN if [ -n ${HTTP_PROXY} ] ; then sed -i -e s'/https/http/' /etc/apk/repositories; fi -COPY docker/pecl_install /usr/local/bin/pecl_install - -# Tune PHP -RUN sed -e 's/^expose_php = On/expose_php = Off/' /usr/local/etc/php/php.ini-production > /usr/local/etc/php/php.ini -RUN sed -i -e 's#^;sendmail_path =#sendmail_path = "/usr/bin/msmtp -t"#' /usr/local/etc/php/php.ini -RUN sed -i -e 's#^memory_limit = 128M#memory_limit = 256M#' /usr/local/etc/php/php.ini -RUN adduser -g "Hosting Admin User" -u 1000 -G www-data -h /var/www/html -HD lamp # Base -RUN apk add --no-cache bash unzip zlib nginx msmtp -RUN curl -SLo /usr/local/bin/wait-for-it https://github.com/vishnubob/wait-for-it/raw/master/wait-for-it.sh && chmod +x /usr/local/bin/wait-for-it +RUN apk add --no-cache bash msmtp memcached -# Memcache -RUN apk add --no-cache memcached libmemcached pkgconfig zlib-dev memcached-dev libmemcached-dev && \ - pecl_install igbinary msgpack memcached && \ - mkdir /run/memcached && chown memcached:memcached /run/memcached && \ - apk del --no-cache pkgconfig zlib-dev memcached-dev libmemcached-dev +# Additional extensions: +RUN install-php-extensions \ + igbinary msgpack memcached zip bz2 zstd brotli gd intl -# Enable ZIP BZIP2 -RUN apk add --no-cache libzip libzip-dev zlib-dev && \ - docker-php-ext-install -j$(nproc) zip bz2 && \ - apk del --no-cache libzip-dev zlib-dev +# Tune PHP +RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini +RUN sed -i -e 's/^memory_limit = 128M/memory_limit = 256M/' /usr/local/etc/php/php.ini +RUN sed -i -e 's/^expose_php = On/expose_php = Off/' /usr/local/etc/php/php.ini +RUN sed -i -e 's#^;sendmail_path =#sendmail_path = "/usr/bin/msmtp -t"#' /usr/local/etc/php/php.ini -# Add zstd -RUN pecl_install zstd - -# Add GD -RUN apk add --no-cache libjpeg libgd libpng freetype freetype-dev zlib-dev libpng-dev jpeg-dev && \ - docker-php-ext-configure gd --with-freetype=/usr/include/freetype2 --with-jpeg=/usr/include/ && \ - docker-php-ext-install -j$(nproc) gd && \ - apk del --no-cache zlib-dev libpng-dev jpeg-dev freetype-dev - -# Add intl -RUN apk add --no-cache icu icu-dev && \ - docker-php-ext-install -j$(nproc) intl && \ - apk del --no-cache icu-dev +# Wait for it +RUN curl -4SLo /usr/local/bin/wait-for-it https://github.com/vishnubob/wait-for-it/raw/master/wait-for-it.sh && chmod +x /usr/local/bin/wait-for-it # Add composer RUN curl -4 https://getcomposer.org/installer|php -- --install-dir=/usr/local/bin --filename=composer ENV COMPOSER_HOME=/var/cache/composer +ENV SITE_USER=www-data + # Other config COPY msmtprc /etc/ -COPY docker/www.conf /usr/local/etc/php-fpm.d/ -COPY docker/nginx-app.conf /etc/nginx/http.d/default.conf +# Startup for ${SITE_USER} COPY docker/init-docker /sbin/init-docker - -# Startup as non-root configuration -RUN chmod 550 /sbin/init-docker && chown www-data:0 /sbin/init-docker -RUN addgroup nginx www-data && addgroup www-data nginx \ - && chgrp www-data /run/nginx /var/log/nginx /var/lib/nginx/tmp \ - && chmod g+w /run/nginx /var/log/nginx \ - && chmod g+rwx /var/lib/nginx/tmp -RUN sed -i -e 's/user nginx;/#user nginx;/' /etc/nginx/nginx.conf -USER www-data +RUN chmod 550 /sbin/init-docker && chown ${SITE_USER}:0 /sbin/init-docker && chown -R ${SITE_USER}:0 ${XDG_DATA_HOME} ${XDG_CONFIG_HOME} VOLUME [ "/var/cache/composer" ] -WORKDIR /var/www/html -EXPOSE 80 +WORKDIR /app +USER ${SITE_USER} + +# Control which port to open +ENV SERVER_NAME=:8080 +EXPOSE 8080 + ENTRYPOINT [ "/sbin/init-docker" ] -CMD [ "php-fpm" ] +CMD [ "--config","/etc/caddy/Caddyfile","--adapter","caddyfile" ] diff --git a/docker/Dockerfile.phptest b/docker/Dockerfile.phptest index 832e640..e4346fb 100644 --- a/docker/Dockerfile.phptest +++ b/docker/Dockerfile.phptest @@ -1,9 +1,9 @@ # NAME docker/php -# VERSION 8.3-fpm-test +# VERSION 8.4-fpm-test -FROM gitea.dege.au/docker/php:8.3-fpm +FROM gitea.dege.au/docker/php:8.4 # Add xdebug -RUN apk --no-cache add linux-headers \ - && pecl_install xdebug \ - && apk --no-cache del linux-headers +USER root +RUN install-php-extensions xdebug +USER ${SITE_USER} diff --git a/docker/init-docker b/docker/init-docker index 7132790..621bc78 100755 --- a/docker/init-docker +++ b/docker/init-docker @@ -3,12 +3,13 @@ set -e role=${CONTAINER_ROLE:-app} env=${APP_ENV:-production} -php=${PHP_DIR:-/var/www/html} +php=${PHP_DIR:-/app} composer=${COMPOSER_HOME:-/var/cache/composer} SITE_USER=${SITE_USER:-www-data} -NGINX_START=${NGINX_START:-TRUE} MEMCACHED_START=${MEMCACHED_START:-FALSE} +RUN_USER=$(id -u) +[ "${RUN_USER}" = "0" ] && USE_SU=1 # To run a local queue, running jobs from the queue "hostname" LOCAL_QUEUE=${LOCAL_QUEUE:-FALSE} @@ -23,14 +24,6 @@ function mp() { echo ${mp} } -function nginx_start() { - # Start NGINX - if [ -x /usr/sbin/nginx -a "${NGINX_START}" == "TRUE" ]; then - echo "* Starting NGINX..." - /usr/sbin/nginx -g 'daemon on; master_process on;' - fi -} - function wait_for_db() { # Wait for DB to be active if [ -n "${DB_HOST}" -a -n "${DB_PORT}" ]; then @@ -42,6 +35,8 @@ function wait_for_db() { fi } +echo "* Started with [$@]" + # Run any container setup [ -x /sbin/init-container ] && /sbin/init-container @@ -53,12 +48,14 @@ fi # Laravel Specific if [ -r artisan -a -e ${php}/.env ]; then + echo "* Laravel Setup..." mp=$(mp ${php}) + echo " - ${php} is an external mount point ${mp}" # Only adjust perms if this is an external mountpoint - if [ ${mp} -eq 0 -o -n "${FORCE_PERMS}" ] ; then - if [ -n "${FORCE_PERMS}" -o "${env}" != "local" -a -z "${SKIP_PERM}" ]; then - echo "* Setting Permissions..." + if [ -n "${BUILD}" -o -n "${FORCE_PERMS}" -o ${mp} -eq 0 ]; then + if [ -n "${BUILD}" -o -n "${FORCE_PERMS}" -o "${env}" != "local" -a -z "${SKIP_PERM}" ]; then + echo " - Setting Permissions..." # Make sure our permissions are appropraite find ${php} -type f -exec chmod 640 {} \; find ${php} -type d -exec chmod 750 {} \; @@ -67,14 +64,14 @@ if [ -r artisan -a -e ${php}/.env ]; then chmod o+rx ${php} chmod a+rx ${php}/artisan chown -R ${SITE_USER}:www-data ${php} - chown -R www-data:www-data ${php}/storage ${php}/bootstrap ${php}/composer.* - [ -e ${php}/vendor ] && chown -R www-data:www-data ${php}/vendor + chown -R ${SITE_USER}:www-data ${php}/storage ${php}/bootstrap ${php}/composer.* + [ -e ${php}/vendor ] && chown -R ${SITE_USER}:www-data ${php}/vendor fi fi - # See if we need to refresh our dependancies + # See if we need to refresh our dependancies (only need if web dir is externally mounted) if [[ -r composer.json && ( -e .composer.refresh || ! -d vendor ) ]]; then - echo "* Composer installing dependancies..." + echo " - Composer installing dependancies..." rm -f ${php}/bootstrap/cache/*.php if [ "${env}" != "local" ]; then @@ -82,39 +79,45 @@ if [ -r artisan -a -e ${php}/.env ]; then fi mp=$(mp ${composer}) + echo " - [${composer}] is a mount point [${mp}]" - if [ ${mp} -eq 0 -o -n "${FORCE_PERMS}" ] ; then - [ -n "${FORCE_PERMS}" -o "${env}" != "local" -a -z "${SKIP_PERM}" ] && chown -R www-data:www-data ${composer} - [ ! -d ${php}/vendor ] && mkdir -m 750 ${php}/vendor && chown www-data:www-data ${php}/vendor - [ -n "${FORCE_PERMS}" -o "${env}" != "local" -a -z "${SKIP_PERM}" ] && chmod g+w ${php} + if [ -n "${BUILD}" -o -n "${FORCE_PERMS}" -o ${mp} -eq 0 ]; then + [ -n "${BUILD}" -o -n "${FORCE_PERMS}" -o "${env}" != "local" -a -z "${SKIP_PERM}" ] && chown -R ${SITE_USER}:www-data ${composer} + [ ! -d ${php}/vendor ] && mkdir -m 750 ${php}/vendor && chown ${SITE_USER}:www-data ${php}/vendor + [ -n "${BUILD}" -o -n "${FORCE_PERMS}" -o "${env}" != "local" -a -z "${SKIP_PERM}" ] && chmod g+w ${php} fi - su www-data -s /bin/sh -c "composer install --optimize-autoloader ${NODEV}" && ( test -e .composer.refresh && rm -f .composer.refresh ) - [ -n "${FORCE_PERMS}" -o "${env}" != "local" -a -z "${SKIP_PERM}" ] && [ ${mp} -eq 0 ] && chmod g-w ${php} + CMD="composer install --optimize-autoloader ${NODEV}" + (( [ -n "${USE_SU}" ] && su ${SITE_USER} -s /bin/sh -c "${CMD}" ) || ${CMD}) && ( test -e .composer.refresh && rm -f .composer.refresh ) + [ -n "${BUILD}" -o -n "${FORCE_PERMS}" -o "${env}" != "local" -a -z "${SKIP_PERM}" ] && [ ${mp} -eq 0 ] && chmod g-w ${php} fi - if [ -e .lumen ]; then - echo "* Lumen detected, not caching configuration..." - else - # We only check for non mount points, in case this container has the app inside - mp=$(mp ${php}) - if [ ${mp} -eq 1 ]; then - echo "* Caching configuration..." - su www-data -s /bin/sh -c "(php artisan optimize)" - fi + # Generate our Encryption Key + [ -z "${BUILD}" ] && [ -z "${APP_KEY}" ] \ + && grep -qe '^APP_KEY=$' .env \ + && echo ' + Encryption Key auto created, replace with with "artisan key:generate --force"' \ + && ./artisan key:generate + + # We only check for non mount points, in case this container has the app inside + mp=$(mp ${php}) + if [ -n "${BUILD}" -o ${mp} -eq 0 ]; then + echo " - Caching configuration..." + CMD="php artisan optimize" + ( [ -n "${USE_SU}" ] && su ${SITE_USER} -s /bin/sh -c "${CMD}" ) || ${CMD} fi if [ "${role}" = "app" ]; then if [ "${env}" != "local" ]; then if [ -z "${IGNORE_MIGRATION}" ]; then if [ -r .migrate ]; then - echo "* Running migration..." + echo " - Running migration..." # If DB_HOST not set, source the env file [ -z "${DB_HOST}" -a -r .env ] && . .env wait_for_db - su www-data -s /bin/sh -c "php artisan migrate" && rm -f .migrate + CMD="php artisan migrate" + (( [ -n "${USE_SU}" ] && su ${SITE_USER} -s /bin/sh -c "${CMD}" ) || ${CMD}) && rm -f .migrate fi else [ -r .migrate ] && echo "! NOTE: Migration ignored due to IGNORE_MIGRATION" @@ -122,24 +125,22 @@ if [ -r artisan -a -e ${php}/.env ]; then # If passport is installed if [ -d ${php}/vendor/laravel/passport ]; then - echo "* Generating OAUTH keys ..." + echo " - Generating OAUTH keys ..." set +e - su www-data -s /bin/sh -c "php artisan passport:keys" + CMD="php artisan passport:keys" + ( [ -n "${USE_SU}" ] && su ${SITE_USER} -s /bin/sh -c "${CMD}" ) || ${CMD} set -e fi fi - nginx_start - if [ "${LOCAL_QUEUE}" = "TRUE" ]; then - echo "* Starting local queue for [$(hostname)${LOCAL_QUEUES:+,${LOCAL_QUEUES}}] with job timeout of [${WORK_TIMEOUT:-90}], trying [${WORK_TRIES:-1}] times..." - su www-data -s /bin/sh -c " - (while true; do php ${PHP_OPTIONS} artisan queue:work --verbose --tries=${WORK_TRIES:-1} --timeout=${WORK_TIMEOUT:-90} --queue=$(hostname)${LOCAL_QUEUES:+,${LOCAL_QUEUES}} ${WORK_MEMORY:+--memory=${WORK_MEMORY}} ${WORK_ONCE:+--once}; done) & - " + echo " - Starting local queue for [$(hostname)${LOCAL_QUEUES:+,${LOCAL_QUEUES}}] with job timeout of [${WORK_TIMEOUT:-90}], trying [${WORK_TRIES:-1}] times..." + CMD="(while true; do php ${PHP_OPTIONS} artisan queue:work --verbose --tries=${WORK_TRIES:-1} --timeout=${WORK_TIMEOUT:-90} --queue=$(hostname)${LOCAL_QUEUES:+,${LOCAL_QUEUES}} ${WORK_MEMORY:+--memory=${WORK_MEMORY}} ${WORK_ONCE:+--once}; done) &" + ( [ -n "${USE_SU}" ] && su ${SITE_USER} -s /bin/sh -c "${CMD}" ) || ${CMD} fi set +e - [ -x init-php.sh ] && su www-data -s /bin/bash "init-php.sh" & + [ -x init-php.sh ] && (( [ -n "${USE_SU}" ] && su ${SITE_USER} -s /bin/sh -c "init-php.sh &" ) || init-php.sh &) exec /usr/local/bin/docker-php-entrypoint "$@" @@ -150,33 +151,25 @@ if [ -r artisan -a -e ${php}/.env ]; then QUEUE_CMD=listen fi - echo "* Running the queue..." + echo " - Running the queue..." # We'll delay starting in case the app is caching sleep 15 wait_for_db - su www-data -s /bin/sh -c " - while true; do - php ${PHP_OPTIONS} artisan queue:${QUEUE_CMD} --verbose --tries=${WORK_TRIES:-1} --timeout=${WORK_TIMEOUT:-90} ${WORK_QUEUES:+--queue=${WORK_QUEUES}} ${WORK_MEMORY:+--memory=${WORK_MEMORY}} ${WORK_ONCE:+--once} - done - " + CMD="while true; do php ${PHP_OPTIONS} artisan queue:${QUEUE_CMD} --verbose --tries=${WORK_TRIES:-1} --timeout=${WORK_TIMEOUT:-90} ${WORK_QUEUES:+--queue=${WORK_QUEUES}} ${WORK_MEMORY:+--memory=${WORK_MEMORY}} ${WORK_ONCE:+--once}; done" + ( [ -n "${USE_SU}" ] && su ${SITE_USER} -s /bin/sh -c "${CMD}" ) || ${CMD} elif [ "$role" = "scheduler" ]; then - echo "* Running the scheduler..." + echo " - Running the scheduler..." # We'll delay starting in case the app is caching sleep 15 - su www-data -s /bin/sh -c " - while true; do - php ${PHP_OPTIONS} artisan schedule:work --verbose --no-interaction - done - " + CMD="while true; do php ${PHP_OPTIONS} artisan schedule:work --verbose --no-interaction; done" + ( [ -n "${USE_SU}" ] && su ${SITE_USER} -s /bin/sh -c "${CMD}" ) || ${CMD} fi else - nginx_start - echo "? NO container role \"${role}\", AND/OR no laravel install, just starting php-fpm" exec /usr/local/bin/docker-php-entrypoint "$@" fi diff --git a/docker/nginx-app.conf b/docker/nginx-app.conf deleted file mode 100644 index cac5a9c..0000000 --- a/docker/nginx-app.conf +++ /dev/null @@ -1,43 +0,0 @@ -server { - listen 80 default_server; - listen [::]:80 default_server; - - access_log off; - client_max_body_size 64m; - error_log /dev/stdout info; - fastcgi_buffering off; - fastcgi_request_buffering off; - gzip_vary on; - gzip_min_length 10240; - gzip_proxied expired no-cache no-store private auth; - gzip_types text/plain text/css application/javascript; - index index.php index.html; - root /var/www/html/public; - server_tokens off; - - set $my_https "off"; - if ($http_x_forwarded_proto = "https") { - set $my_https "on"; - } - - location / { - try_files $uri $uri/ /index.php?$query_string; - } - - location ~ \.php$ { - try_files $uri =404; - fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass 127.0.0.1:9000; - fastcgi_index index.php; - - include fastcgi_params; - - fastcgi_param HTTPS $my_https; - fastcgi_param PATH_INFO $fastcgi_path_info; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_param SERVER_NAME $host; - - fastcgi_read_timeout 600s; - fastcgi_send_timeout 600s; - } -} diff --git a/docker/pecl_install b/docker/pecl_install deleted file mode 100755 index 3e75220..0000000 --- a/docker/pecl_install +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -# This will install our PHP modules -# call peck-install module1 module2 - -# First install some dependancies -apk add --no-cache autoconf gcc libc-dev make - -# Install the modules -for module in $@; do - pecl install -o -f ${module} && docker-php-ext-enable ${module} -done - -# Clean up -rm -rf /tmp/pear -apk del --no-cache autoconf gcc libc-dev make diff --git a/docker/www.conf b/docker/www.conf deleted file mode 100644 index 1b869d3..0000000 --- a/docker/www.conf +++ /dev/null @@ -1,12 +0,0 @@ -[www] -;group = www-data -listen = 127.0.0.1:9000 -pm = dynamic -pm.max_children = 25 -pm.max_spare_servers = 10 -pm.min_spare_servers = 5 -pm.start_servers = 10 -;user = www-data -prefix = /var/www/html -php_admin_value[memory_limit] = 512M -php_admin_value[max_execution_time] = 300