From c8021f204db2f443107745ca89c7984b55d9c05b Mon Sep 17 00:00:00 2001 From: Nick Yeoman Date: Sat, 15 Mar 2025 00:38:49 -0700 Subject: [PATCH] php version 8.4.5 debian rebuild v6 --- .gitignore | 1 + 000-default.conf | 16 +++++ Dockerfile | 103 ++++++++++++---------------- README.md | 72 +++++++++++++++----- docker-compose.yml | 68 ++++++++++--------- env-sample | 8 --- php.ini | 163 +++++++++++++-------------------------------- public/test.php | 155 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 350 insertions(+), 236 deletions(-) create mode 100644 .gitignore create mode 100644 000-default.conf delete mode 100644 env-sample create mode 100644 public/test.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8fce603 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +data/ diff --git a/000-default.conf b/000-default.conf new file mode 100644 index 0000000..086fe3c --- /dev/null +++ b/000-default.conf @@ -0,0 +1,16 @@ +# Global log redirection to stdout and stderr +ErrorLog "|/usr/bin/tee -a /var/log/apache2/error.log" +CustomLog "|/usr/bin/tee -a /var/log/apache2/access.log" combined + + + DocumentRoot /data/public + + Options Indexes FollowSymLinks + AllowOverride All + Require all granted + + + # Remote IP configuration + RemoteIPHeader X-Forwarded-For + RemoteIPTrustedProxy 127.0.0.1 + diff --git a/Dockerfile b/Dockerfile index 39c6434..c7611e3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,70 +1,53 @@ -################################################################################################################################# -# Project: https://git.4lt.ca/4lt/phpcontainer/ -# v 5.0.1 -################################################################################################################################# +FROM debian:bookworm-20250224 -FROM php:8.4.2-apache - -# Set maintainer information -LABEL version="5.0.1" -LABEL maintainer="4 Lights Consulting " -LABEL description="Production-ready PHP Apache container" -LABEL org.label-schema.vcs-url="https://git.4lt.ca/4lt/phpcontainer" - -# Set working directory and Apache document root WORKDIR /data -ENV APACHE_DOCUMENT_ROOT=/data/public/ -# Update and install required packages -RUN set -eux; \ +# Install necessary packages and configure PHP repository +RUN apt-get update && apt-get install -y \ + lsb-release ca-certificates curl apt-transport-https logrotate ssl-cert apache2 && \ + echo "ServerName localhost" >> /etc/apache2/apache2.conf && \ + curl -sSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb && \ + dpkg -i /tmp/debsuryorg-archive-keyring.deb && \ + sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list' && \ apt-get update && \ - apt-get install -y --no-install-recommends \ - ghostscript \ - libssl-dev \ - libbz2-dev \ - libfreetype6-dev \ - libjpeg-dev \ - libpng-dev \ - libwebp-dev \ - libzip-dev && \ - rm -rf /var/lib/apt/lists/* + apt-get install -y \ + php8.4 php8.4-cli php8.4-fpm php8.4-mysql php8.4-xml php8.4-mbstring php8.4-curl php8.4-zip php8.4-redis libapache2-mod-php8.4 && \ + apt-get autoremove -y && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* /tmp/* -# Configure and install essential PHP extensions -RUN set -ex; \ - docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp; \ - docker-php-ext-install -j "$(nproc)" \ - bz2 \ - gd \ - mysqli \ - pdo_mysql \ - zip +# log management +RUN cat < /etc/logrotate.d/apache2 +/var/log/apache2/*.log { + weekly + missingok + rotate 4 + compress + delaycompress + notifempty + create 640 root adm +} +EOF -# Set recommended PHP.ini settings -RUN set -eux; \ - echo 'opcache.memory_consumption=128' > /usr/local/etc/php/conf.d/opcache-recommended.ini; \ - echo 'opcache.interned_strings_buffer=8' >> /usr/local/etc/php/conf.d/opcache-recommended.ini; \ - echo 'opcache.max_accelerated_files=4000' >> /usr/local/etc/php/conf.d/opcache-recommended.ini; \ - echo 'opcache.revalidate_freq=2' >> /usr/local/etc/php/conf.d/opcache-recommended.ini; \ - echo 'opcache.fast_shutdown=1' >> /usr/local/etc/php/conf.d/opcache-recommended.ini; \ - echo 'error_reporting = E_ERROR | E_WARNING | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_RECOVERABLE_ERROR' > /usr/local/etc/php/conf.d/error-logging.ini; \ - echo 'display_errors = Off' >> /usr/local/etc/php/conf.d/error-logging.ini; \ - echo 'log_errors = On' >> /usr/local/etc/php/conf.d/error-logging.ini; \ - echo 'error_log = /dev/stderr' >> /usr/local/etc/php/conf.d/error-logging.ini - -# Enable Apache modules and configure RemoteIP -RUN set -eux; \ - a2enmod expires headers rewrite remoteip socache_shmcb ssl; \ - echo 'RemoteIPHeader X-Forwarded-For' > /etc/apache2/conf-available/remoteip.conf; \ - echo 'RemoteIPTrustedProxy 10.0.0.0/8' >> /etc/apache2/conf-available/remoteip.conf; \ - echo 'RemoteIPTrustedProxy 172.16.0.0/12' >> /etc/apache2/conf-available/remoteip.conf; \ - echo 'RemoteIPTrustedProxy 192.168.0.0/16' >> /etc/apache2/conf-available/remoteip.conf; \ - a2enconf remoteip; \ +RUN echo 'RemoteIPHeader X-Forwarded-For' > /etc/apache2/conf-available/remoteip.conf && \ + echo 'RemoteIPTrustedProxy 127.0.0.1' >> /etc/apache2/conf-available/remoteip.conf && \ + a2enconf remoteip && \ sed -ri 's/([[:space:]]*LogFormat[[:space:]]+"[^"]*)%h([^"]*")/\1%a\2/g' /etc/apache2/*.conf -# More Apache settings -RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf -RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf -RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf +RUN mkdir -p /php && echo "PHP_INI_SCAN_DIR=/php" > /etc/environment +COPY php.ini /php/php.ini +COPY 000-default.conf /etc/apache2/sites-available/000-default.conf + +# Security headers for Apache +RUN echo 'Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"' >> /etc/apache2/conf-available/security.conf && \ + echo 'Header always set X-Content-Type-Options "nosniff"' >> /etc/apache2/conf-available/security.conf && \ + echo 'Header always set X-XSS-Protection "1; mode=block"' >> /etc/apache2/conf-available/security.conf && \ + echo 'Header always set X-Frame-Options "SAMEORIGIN"' >> /etc/apache2/conf-available/security.conf + +RUN a2enmod expires headers rewrite remoteip socache_shmcb ssl EXPOSE 80 -CMD ["apache2-foreground"] +CMD ["apachectl", "-D", "FOREGROUND"] + +HEALTHCHECK --interval=30s --timeout=10s --retries=3 \ + CMD curl --silent --fail localhost:80 || exit 1 diff --git a/README.md b/README.md index d8dfa07..261bfe2 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,68 @@ # 4 Lights Consulting -The apache php docker container that 4 Lights uses for production. - Dockerhub: https://hub.docker.com/r/4lights/phpcontainer +Git Repo: https://git.4lt.ca/4lt/phpcontainer -## How to update +This repository provides a production-ready Docker container for running PHP with Apache. +It comes pre-configured with the necessary PHP extensions, Apache modules, and is optimized for [Novaconium Framework](https://git.4lt.ca/4lt/novaconium). -1. Clone the project: ```git clone git@git.4lt.ca:4lt/phpcontainer.git``` -2. Update the Dockerfile. -3. Build (be sure to change the version number) +## Features + +- **PHP Version**: 8.4.5 +- **Apache Web Server**: Configured to run PHP applications +- **Enabled Apache Modules**: + - `expires` + - `headers` + - `rewrite` + - `remoteip` + - `socache_shmcb` + - `ssl` +- **PHP Extensions**: + - `mysqli` + - `pdo_mysql` + - `pdo_pgsql` + - `pgsql` + - `pdo_sqlite` + - `sqlite3` + - `gd` + - `intl` + - `zip` + - `opcache` + - `bcmath` + - Redis (via PECL) +- **Email Setup**: Configured to use msmtp for sending emails +- **Timezone**: Default set to Vancouver (`America/Vancouver`) +- **PHP Session Storage**: Supports Redis as the default, with fallback to file-based sessions + +## Getting Started + +Follow these steps to set up the PHP container on your local environment. + +### Prerequisites + +1. Docker +2. Docker Compose is recommended +3. Alternatively Podman is supported + +### Usage + +#### Clone the Repository + +```bash +git clone https://git.4lt.ca/4lt/phpcontainer.git +cd phpcontainer +docker build -t php-apache-container . +``` +## How to update on dockerhub ```bash sudo su -docker buildx build --no-cache -t 4lights/phpcontainer:5.0.1 -t 4lights/phpcontainer:latest --load . +docker buildx build --no-cache -t 4lights/phpcontainer:6.0.0 -t 4lights/phpcontainer:latest --load . docker login -docker push 4lights/phpcontainer:5.0.1 +docker push 4lights/phpcontainer:6.0.0 docker push 4lights/phpcontainer:latest ``` # References And Notes -* [Stack Overflow IMAP features](https://stackoverflow.com/questions/49854767/docker-php7-2-fpm-cant-install-imap-module) -* Joomla base used: f9a16bcbd8/4.3/php8.1/apache/Dockerfile - -## Supported Software - -* 4 Lights PHP Framework - -## Samples included in Repo - -There is a docker-compose, env-sample and php.ini included as sample data. \ No newline at end of file +Test using test.php diff --git a/docker-compose.yml b/docker-compose.yml index c8c5c32..82d61fb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,36 +1,40 @@ ---- -# Sample Docker Compose File +# Sample Docker Compose +services: + php-apache: + #image: 4lights/phpcontainer:6.0.0 + image: debianphp + ports: + - "8000:80" + volumes: + - ./:/data # looks for /data/public + - ./php.ini:/php/php.ini # Optional override php.ini + - ./data/logs:/var/log/apache2 # Optional Logs + restart: unless-stopped + networks: + - proxy + - internal -version: "3.3" + redis: + image: redis:latest + networks: + - internal + restart: unless-stopped -volumes: - db: + mariadb: + image: mariadb:latest + environment: + MYSQL_ROOT_PASSWORD: rootpassword + MYSQL_DATABASE: dbname + MYSQL_USER: user + MYSQL_PASSWORD: password + volumes: + - ./data/db:/var/lib/mysql + networks: + - internal + restart: unless-stopped networks: - default: - external: - name: ${NETWORKNAME} - -services: - - db: - image: mariadb:latest - restart: always - container_name: "${DBHOST}" - environment: - MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} - MYSQL_PASSWORD: ${DBPASSWORD} - MYSQL_DATABASE: ${DB} - MYSQL_USER: ${DBUSER} - volumes: - - "db:/var/lib/mysql" - - php-app: - container_name: "${DOCKERNAME}" - image: "4lights/phpcontainer:latest" - restart: always - volumes: - - "./:/data" - - ./php.ini:/usr/local/etc/php/php.ini - ports: - - "${DOCKERPORT}:80" \ No newline at end of file + proxy: + external: true + internal: + driver: bridge \ No newline at end of file diff --git a/env-sample b/env-sample deleted file mode 100644 index cbcb2eb..0000000 --- a/env-sample +++ /dev/null @@ -1,8 +0,0 @@ -NETWORKNAME=PROXY_NETWORK -DBHOST=DB_HOST_NAME -MYSQL_ROOT_PASSWORD=ChangeMe -DBPASSWORD=ChangeMeAlso -DB=DATABASENAME -DBUSER=DBUSERNAME -DOCKERNAME=Container_name -DOCKERPORT=8000 \ No newline at end of file diff --git a/php.ini b/php.ini index bdded12..7706bf4 100644 --- a/php.ini +++ b/php.ini @@ -1,128 +1,55 @@ [PHP] -engine = On -short_open_tag = Off -precision = 14 -output_buffering = 4096 -zlib.output_compression = Off -implicit_flush = Off -unserialize_callback_func = -serialize_precision = -1 -disable_functions = -disable_classes = -zend.enable_gc = On -zend.exception_ignore_args = On -zend.exception_string_param_max_len = 0 -expose_php = On +; Basic PHP settings max_execution_time = 30 +memory_limit = 500M +upload_max_filesize = 100M +post_max_size = 100M max_input_time = 60 -memory_limit = 128M -error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT -display_errors = Off -display_startup_errors = Off +date.timezone = America/Vancouver + +; Error handling +display_errors = On +display_startup_errors = On log_errors = On -log_errors_max_len = 1024 -ignore_repeated_errors = Off -ignore_repeated_source = Off -report_memleaks = On -variables_order = "GPCS" -request_order = "GP" -register_argc_argv = Off -auto_globals_jit = On -post_max_size = 800M -auto_prepend_file = -auto_append_file = -default_mimetype = "text/html" -default_charset = "UTF-8" -doc_root = -user_dir = -enable_dl = Off -file_uploads = On -upload_max_filesize = 400M -max_file_uploads = 20 -allow_url_fopen = On -allow_url_include = Off -default_socket_timeout = 60 +error_log = /var/log/php_errors.log -[CLI Server] -cli_server.color = On - -[Pdo_mysql] -pdo_mysql.default_socket= - -[mail function] -SMTP = localhost -smtp_port = 25 -mail.add_x_header = Off - -[ODBC] -odbc.allow_persistent = On -odbc.check_persistent = On -odbc.max_persistent = -1 -odbc.max_links = -1 -odbc.defaultlrl = 4096 -odbc.defaultbinmode = 1 - -[MySQLi] -mysqli.max_persistent = -1 -mysqli.allow_persistent = On -mysqli.max_links = -1 -mysqli.default_port = 3306 -mysqli.default_socket = -mysqli.default_host = -mysqli.default_user = -mysqli.default_pw = -mysqli.reconnect = Off - -[mysqlnd] -mysqlnd.collect_statistics = On -mysqlnd.collect_memory_statistics = Off - -[PostgreSQL] -pgsql.allow_persistent = On -pgsql.auto_reset_persistent = Off -pgsql.max_persistent = -1 -pgsql.max_links = -1 -pgsql.ignore_notice = 0 -pgsql.log_notice = 0 - -[bcmath] -bcmath.scale = 0 - -[Session] -session.save_handler = files -session.use_strict_mode = 0 -session.use_cookies = 1 -session.use_only_cookies = 1 -session.name = PHPSESSID -session.auto_start = 0 -session.cookie_lifetime = 0 -session.cookie_path = / -session.cookie_domain = -session.cookie_httponly = -session.cookie_samesite = -session.serialize_handler = php -session.gc_probability = 1 -session.gc_divisor = 1000 +; Session settings +session.save_path = "/var/lib/php/sessions" session.gc_maxlifetime = 1440 -session.referer_check = -session.cache_limiter = nocache -session.cache_expire = 180 -session.use_trans_sid = 0 -session.sid_length = 26 -session.trans_sid_tags = "a=href,area=href,frame=src,form=" -session.sid_bits_per_character = 5 +session.cookie_lifetime = 0 +session.use_strict_mode = 1 -[Assertion] -zend.assertions = -1 +; Realpath cache +realpath_cache_size = 4096k +realpath_cache_ttl = 120 -[Tidy] -tidy.clean_output = Off +; File upload settings +file_uploads = On +allow_url_fopen = On -[soap] -soap.wsdl_cache_enabled=1 -soap.wsdl_cache_dir="/tmp" -soap.wsdl_cache_ttl=86400 -soap.wsdl_cache_limit = 5 +; Redis settings (ensure Redis extension is loaded) +extension=redis.so -[ldap] -ldap.max_links = -1 +; mbstring settings (useful for multi-byte encoding handling) +mbstring.language = Japanese +mbstring.internal_encoding = UTF-8 +mbstring.http_input = auto +mbstring.http_output = UTF-8 +mbstring.detect_order = auto +mbstring.substitute_character = none + +; cURL settings +curl.cainfo = "/etc/ssl/certs/ca-certificates.crt" + +; SMTP settings (for sending mail, if needed) +SMTP = localhost +sendmail_path = /usr/sbin/sendmail -t -i + +; Extension loading +extension=curl +extension=mbstring +extension=redis +extension=xml +extension=mysqli +extension=pdo_mysql +extension=zip \ No newline at end of file diff --git a/public/test.php b/public/test.php new file mode 100644 index 0000000..3ee7e71 --- /dev/null +++ b/public/test.php @@ -0,0 +1,155 @@ + + + + + + Server Test - Debian PHP Apache + + + + +
+

PHP Container Test Script

+

Four Lights PHP Container

+ + +

Server Information

+ + + + + + +
PHP Version
Current Date/Time (Vancouver)
upload_max_filesize
post_max_size
php.ini
+ +

Redis Test

+ connect('redis', 6379); + echo "

✅ Redis connected

"; + $redis->set("test_key", "There are FOUR Lights!"); + echo "

Redis test_key: " . $redis->get("test_key") . "

"; + } catch (Exception $e) { + echo "

❌ Redis connection failed: " . $e->getMessage() . "

"; + } + ?> + +

MariaDB Test

+ connect_error) { + echo "

❌ MariaDB connection failed: " . $mysqli->connect_error . "

"; + } else { + echo "

✅ MariaDB connected

"; + $result = $mysqli->query('SELECT NOW()'); + $row = $result->fetch_row(); + echo "

Current time in MariaDB: " . $row[0] . "

"; + $mysqli->close(); + } + ?> + +

RemoteIP Test

+

Your IP address (from Apache's remoteip module):

+ + + +

File Upload Test

+
+
+ + +
+
+ + ✅ File uploaded successfully to: " . htmlspecialchars($destination) . "

"; + echo "

Size: " . $_FILES['testfile']['size'] . " bytes

"; + } else { + echo "

❌ Error moving file.

"; + } + } else { + echo "

❌ Error uploading file. Error Code: " . $_FILES['testfile']['error'] . "

"; + } + } + + ?> +
+ + +