diff --git a/.gitignore b/.gitignore index 382b76f..0dfb911 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ !entrypoint/entrypoint.sh !nginx !nginx/default.conf +!nginx/nginx.conf !php !php/settings.ini !php/www.conf diff --git a/Dockerfile b/Dockerfile index 0f1303c..3727b0c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.19 +FROM alpine LABEL maintainer="João Pinto [suport@joaopinto.pt]" @@ -6,8 +6,9 @@ LABEL maintainer="João Pinto [suport@joaopinto.pt]" RUN apk update && apk add --no-cache \ php83 \ php83-fpm \ - nginx=1.24.0-r15 \ - supervisor=4.2.5-r4 && \ + nginx \ + supervisor \ + tzdata && \ rm -rf /var/cache/apk/* # Copy PHP configuration file @@ -20,6 +21,7 @@ RUN mv /usr/bin/php83 /usr/bin/php && \ # Copy Nginx configuration file and entrypoint script COPY nginx/default.conf /etc/nginx/http.d/default.conf +COPY nginx/nginx.conf /etc/nginx/nginx.conf COPY entrypoint/entrypoint.sh /usr/local/bin/entrypoint.sh # Make the startup script executable diff --git a/README.md b/README.md index b7f7606..5ff6deb 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@ in a production environment. ## 📖 Project Description -    ***Production*** is a *Docker* image created using the Linux distribution ***Alpine*** version 3.19. +    ***Production*** is a *Docker* image created using the Linux distribution ***Alpine***. The ***PHP*** interpreter version 8.3 was installed, including the extensions *core, date, filter, hash, json, libxml, pcre, -random, readline, reflection, spl, standard, and zlib*. In addition, the web server ***NGINX*** version 1.24.0-r15 was installed +random, readline, reflection, spl, standard, and zlib*. In addition, the web server ***NGINX*** was installed to allow the efficient execution of your web projects. -    To facilitate the management of processes, the ***Supervisor*** version 4.2.5-r4 was installed, which allows +    To facilitate the management of processes, the ***Supervisor*** was installed, which allows the control of the execution of multiple processes, such as the web server and the PHP interpreter. The ***Supervisor*** is also responsible for monitoring and restarting processes in case of failures, ensuring greater availability of your project. @@ -47,7 +47,7 @@ To run your project in the Docker image ***Production***, follow the steps below 2. **Execution File**: If the execution file of your project `index.php` is not in the `/var/www/html` directory, you can define the directory of your project through the `INDEX_PATH` environment variable. -3. ***PHP* Extensions**: If your project requires additional *PHP* extensions or adjustments in the *PHP* settings, you can define the `PHP_EXTENSIONS`, `MEMORY_LIMIT`, and `UPLOAD_MAX` environment variables as needed. +3. ***PHP* Extensions**: If your project requires additional *PHP* extensions or adjustments in the *PHP* settings, you can define the `PHP_EXTENSIONS`, `MEMORY_LIMIT`, and `UPLOAD_MAX_SIZE` environment variables as needed. 4. ***Additional Processes***: If you need to run more processes in addition to those existing in the image (for example, queues, workers, etc.), you can use the `SUPERVISOR_CONF` environment variable to indicate the path of the *Supervisor* configuration file. @@ -58,6 +58,7 @@ By following these steps, you will be able to run your project in the *Docker* i ## 📑 Environment Variables - **PHP_EXTENSIONS**: The *PHP* extensions to be installed. Default: null (e.g.: pdo_mysql mysqli) +- **TIMEZONE**: The timezone to be used by system. Default: UTC ([List of Timezones](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)) - **INDEX_PATH**: The directory where the execution file of your project is located. Default: /var/www/html - **MEMORY_LIMIT**: The memory limit that *PHP* can use. Default: 128M - **UPLOAD_MAX**: The maximum size of files that can be uploaded. Default: 8M @@ -67,7 +68,7 @@ By following these steps, you will be able to run your project in the *Docker* i ### - Using the command line: ``` -docker run -d -p 80:80 -v /path/to/your/project:/var/www/html -e PHP_EXTENSIONS="pdo_mysql mysqli" -e MEMORY_LIMIT=256M -e UPLOAD_MAX=16M -e INDEX_PATH=/var/www/html/public production +docker run -d -p 80:80 -v /path/to/your/project:/var/www/html -e PHP_EXTENSIONS="pdo_mysql mysqli" -e TIMEZONE=Europe/Lisbon -e MEMORY_LIMIT=256M -e UPLOAD_MAX_SIZE=16M -e INDEX_PATH=/var/www/html/public -e SUPERVISOR_CONF=/var/www/html/supervisor.conf production ``` ### - Using *Docker Compose*: ``` @@ -80,9 +81,11 @@ services: - ./path/to/your/project:/var/www/html environment: - PHP_EXTENSIONS=pdo_mysql mysqli + - TIMEZONE=Europe/Lisbon - MEMORY_LIMIT=256M - - UPLOAD_MAX=16M + - UPLOAD_MAX_SIZE=16M - INDEX_PATH=/var/www/html/public + - SUPERVISOR_CONF=/var/www/html/supervisor.conf ``` ## 📝 Issues and Suggestions diff --git a/entrypoint/entrypoint.sh b/entrypoint/entrypoint.sh index 294c64e..a4aa702 100644 --- a/entrypoint/entrypoint.sh +++ b/entrypoint/entrypoint.sh @@ -2,13 +2,15 @@ # Define default values for environment variables if they are not set PHP_EXTENSIONS=${PHP_EXTENSIONS:-} +TIMEZONE=${TIMEZONE:-UTC} INDEX_PATH=${INDEX_PATH:-/var/www/html} MEMORY_LIMIT=${MEMORY_LIMIT:-128M} -UPLOAD_MAX=${UPLOAD_MAX:-8M} +UPLOAD_MAX_SIZE=${UPLOAD_MAX_SIZE:-8M} SUPERVISOR_CONF=${SUPERVISOR_CONF:-} # Define file paths -NGINX_CONF="/etc/nginx/http.d/default.conf" +NGINX_CONF="/etc/nginx/nginx.conf" +NGINX_VIRTUAL_HOST_CONF="/etc/nginx/http.d/default.conf" PHP_INI="/etc/php83/conf.d/settings.ini" PHP_FPM_CONF="/etc/php83/php-fpm.d/www.conf" @@ -51,9 +53,16 @@ check_and_install_extension() { fi } +# Set the timezone +if [ -n "${TIMEZONE}" ]; then + ln -snf "/usr/share/zoneinfo/${TIMEZONE}" /etc/localtime || { echo "Failed to set timezone to '${TIMEZONE}'."; exit 1; } + echo "${TIMEZONE}" > /etc/timezone || { echo "Failed to set timezone to '${TIMEZONE}'."; exit 1; } +fi + # Replace placeholders with actual values in configuration files -sed -i "s|INDEX_PATH|${INDEX_PATH}|;s|UPLOAD_MAX|${UPLOAD_MAX}|" ${NGINX_CONF} || { echo "Failed to replace placeholders in ${NGINX_CONF}."; exit 1; } -sed -i "s|MEMORY_LIMIT|${MEMORY_LIMIT}|;s|UPLOAD_MAX|${UPLOAD_MAX}|" ${PHP_INI} || { echo "Failed to replace placeholders in ${PHP_INI}."; exit 1; } +sed -i "s|UPLOAD_MAX_SIZE|${UPLOAD_MAX_SIZE}|" ${NGINX_CONF} || { echo "Failed to replace placeholders in ${NGINX_CONF}."; exit 1; } +sed -i "s|INDEX_PATH|${INDEX_PATH}|;s|UPLOAD_MAX_SIZE|${UPLOAD_MAX_SIZE}|" ${NGINX_VIRTUAL_HOST_CONF} || { echo "Failed to replace placeholders in ${NGINX_VIRTUAL_HOST_CONF}."; exit 1; } +sed -i "s|MEMORY_LIMIT|${MEMORY_LIMIT}|;s|UPLOAD_MAX_SIZE|${UPLOAD_MAX_SIZE}|" ${PHP_INI} || { echo "Failed to replace placeholders in ${PHP_INI}."; exit 1; } sed -i "s|MEMORY_LIMIT|${MEMORY_LIMIT}|" ${PHP_FPM_CONF} || { echo "Failed to replace placeholders in ${PHP_FPM_CONF}."; exit 1; } # Check if the SUPERVISOR_CONF environment variable is set diff --git a/nginx/default.conf b/nginx/default.conf index 20f660c..a021c94 100644 --- a/nginx/default.conf +++ b/nginx/default.conf @@ -3,12 +3,6 @@ server { listen 80; listen [::]:80; - # Server tokens - server_tokens off; - - # Charset - charset utf-8; - # Root directory and index file root INDEX_PATH; index index.php; @@ -17,17 +11,6 @@ server { add_header X-Frame-Options "SAMEORIGIN"; add_header X-Content-Type-Options "nosniff"; - # Gzip settings - gzip on; - gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; - - # Client body size limit - client_max_body_size UPLOAD_MAX; - - # Logging - access_log /dev/stdout; - error_log /dev/stderr; - # Main location block location / { try_files $uri $uri/ /index.php?$query_string; diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000..7d8d35e --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,111 @@ +# /etc/nginx/nginx.conf + +user nginx; + +# Set number of worker processes automatically based on number of CPU cores. +worker_processes auto; + +# Enables the use of JIT for regular expressions to speed-up their processing. +pcre_jit on; + +# Configures default error logger. +error_log /var/log/nginx/error.log warn; + +# Includes files with directives to load dynamic modules. +include /etc/nginx/modules/*.conf; + +# Include files with config snippets into the root context. +include /etc/nginx/conf.d/*.conf; + +events { + # The maximum number of simultaneous connections that can be opened by + # a worker process. + worker_connections 2048; +} + +http { + # Set charset to utf-8. + charset utf-8; + + # Includes mapping of file name extensions to MIME types of responses + # and defines the default type. + include /etc/nginx/mime.types; + default_type application/octet-stream; + + # Don't tell nginx version to the clients. Default is 'on'. + server_tokens off; + + # Specifies the maximum accepted body size of a client request, as + # indicated by the request header Content-Length. If the stated content + # length is greater than this size, then the client receives the HTTP + # error code 413. Set to 0 to disable. Default is '1m'. + client_max_body_size UPLOAD_MAX_SIZE; + + # Sendfile copies data between one FD and other from within the kernel, + # which is more efficient than read() + write(). Default is off. + sendfile on; + + # Causes nginx to attempt to send its HTTP response head in one packet, + # instead of using partial frames. Default is 'off'. + tcp_nopush on; + + + # Enables the specified protocols. Default is TLSv1 TLSv1.1 TLSv1.2. + # TIP: If you're not obligated to support ancient clients, remove TLSv1.1. + ssl_protocols TLSv1.2 TLSv1.3; + + # Specifies that our cipher suits should be preferred over client ciphers. + # Default is 'off'. + ssl_prefer_server_ciphers on; + + # Enables a shared SSL cache with size that can hold around 8000 sessions. + # Default is 'none'. + ssl_session_cache shared:SSL:2m; + + # Specifies a time during which a client may reuse the session parameters. + # Default is '5m'. + ssl_session_timeout 1h; + + # Disable TLS session tickets (they are insecure). Default is 'on'. + ssl_session_tickets off; + + # Enable gzipping of responses. + gzip on; + + # Set the Vary HTTP header as defined in the RFC 2616. Default is 'off'. + gzip_vary on; + + # Set the list of MIME types that are compressed by gzip. + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + # Helper variable for proxying websockets. + map $http_upgrade $connection_upgrade { + default upgrade; + '' close; + } + + # Remove health check logs from the container + map "$remote_addr:$request_uri:$status:$http_user_agent" $health_check { + ~*^(127\.0\.0\.1|::1):/:200:Wget 0; + default 1; + } + + # Specifies the main log format. + log_format main '{ ' + '"time_local": "$time_local", ' + '"request": "$request", ' + '"status": $status, ' + '"body_bytes_sent": $body_bytes_sent, ' + '"http_referer": "$http_referer", ' + '"http_user_agent": "$http_user_agent", ' + '"http_x_forwarded_for": "$http_x_forwarded_for", ' + '"http_cf_connecting_ip": "$http_cf_connecting_ip", ' + '"remote_addr": "$remote_addr" ' + '}'; + + # Sets the path, format, and configuration for a buffered log write. + access_log /var/log/nginx/access.log main if=$health_check; + + # Includes virtual hosts configs. + include /etc/nginx/http.d/*.conf; +} \ No newline at end of file diff --git a/php/settings.ini b/php/settings.ini index aad7951..cf5139d 100644 --- a/php/settings.ini +++ b/php/settings.ini @@ -9,8 +9,8 @@ max_execution_time = 300 memory_limit = MEMORY_LIMIT ; File uploads -upload_max_filesize = UPLOAD_MAX -post_max_size = UPLOAD_MAX +upload_max_filesize = UPLOAD_MAX_SIZE +post_max_size = UPLOAD_MAX_SIZE ; Enable opcache opcache.enable=1