From 11468a754801b7943fbed482d4e9ee5bf2ac84dc Mon Sep 17 00:00:00 2001
From: 0xd9a <0xd9a@noreply.codeberg.org>
Date: Tue, 14 May 2024 16:58:36 +0530
Subject: [PATCH] Add Docker configurations

---
 Dockerfile                        | 56 +++++++++++++++++++++++++++++++
 README.md                         |  7 ++--
 docker_config/conf.d/default.conf | 56 +++++++++++++++++++++++++++++++
 docker_config/fpm-pool.conf       | 56 +++++++++++++++++++++++++++++++
 docker_config/nginx.conf          | 47 ++++++++++++++++++++++++++
 docker_config/php.ini             |  3 ++
 docker_config/supervisord.conf    | 23 +++++++++++++
 7 files changed, 246 insertions(+), 2 deletions(-)
 create mode 100644 Dockerfile
 create mode 100644 docker_config/conf.d/default.conf
 create mode 100644 docker_config/fpm-pool.conf
 create mode 100644 docker_config/nginx.conf
 create mode 100644 docker_config/php.ini
 create mode 100644 docker_config/supervisord.conf

diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..ad5dd2d
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,56 @@
+FROM composer as composer
+
+COPY --chown=nobody . /app
+RUN composer install --optimize-autoloader --no-interaction --no-progress
+
+FROM alpine:3.19
+
+# Install packages and remove default server definition
+RUN apk add --no-cache \
+  curl \
+  nginx \
+  php83 \
+  php83-ctype \
+  php83-curl \
+  php83-dom \
+  php83-fpm \
+  php83-intl \
+  php83-mbstring \
+  php83-session \
+  php83-tokenizer \
+  php83-simplexml \
+  supervisor
+
+# Configure nginx - http
+COPY docker_config/nginx.conf /etc/nginx/nginx.conf
+# Configure nginx - default server
+COPY docker_config/conf.d /etc/nginx/conf.d/
+
+# Configure PHP-FPM
+ENV PHP_INI_DIR /etc/php83
+COPY docker_config/fpm-pool.conf ${PHP_INI_DIR}/php-fpm.d/www.conf
+COPY docker_config/php.ini ${PHP_INI_DIR}/conf.d/custom.ini
+
+# Configure supervisord
+COPY docker_config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
+
+# Add application
+COPY --chown=nobody --from=composer /app/ /var/www/fediplan/
+
+# Make sure files/folders needed by the processes are accessable when they run under the nobody user
+RUN chown -R nobody.nobody /var/www/fediplan /run /var/lib/nginx /var/log/nginx
+
+# Create symlink for php
+RUN ln -s /usr/bin/php83 /usr/bin/php
+
+# Switch to use a non-root user from here on
+USER nobody
+
+# Expose the port nginx is reachable on
+EXPOSE 8080
+
+# Let supervisord start nginx & php-fpm
+CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
+
+# Configure a healthcheck to validate that everything is up&running
+HEALTHCHECK --timeout=10s CMD curl --silent --fail http://127.0.0.1:8080/fpm-ping || exit 1
diff --git a/README.md b/README.md
index 59d4276..81c2520 100644
--- a/README.md
+++ b/README.md
@@ -27,5 +27,8 @@ See: [Download Composer](https://getcomposer.org/download/)
 
 Your site needs to target /path/to/FediPlan/public
 
-    
-#### Support My work at [fedilab.app](https://fedilab.app/page/donations/)
\ No newline at end of file
+
+#### Support My work at [fedilab.app](https://fedilab.app/page/donations/)
+
+#### Credits
+Docker configurations are based on [github.com/TrafeX/docker-php-nginx](https://github.com/TrafeX/docker-php-nginx)
diff --git a/docker_config/conf.d/default.conf b/docker_config/conf.d/default.conf
new file mode 100644
index 0000000..bd1ee7d
--- /dev/null
+++ b/docker_config/conf.d/default.conf
@@ -0,0 +1,56 @@
+# Default server definition
+server {
+    listen [::]:8080 default_server;
+    listen 8080 default_server;
+    server_name _;
+
+    sendfile off;
+    tcp_nodelay on;
+    absolute_redirect off;
+
+    root /var/www/fediplan/public;
+    index index.php index.html;
+
+    location / {
+        # First attempt to serve request as file, then
+        # as directory, then fall back to index.php
+        try_files $uri $uri/ /index.php?q=$uri&$args;
+    }
+
+    # Redirect server error pages to the static page /50x.html
+    error_page 500 502 503 504 /50x.html;
+    location = /50x.html {
+        root /var/lib/nginx/html;
+    }
+
+    # Pass the PHP scripts to PHP-FPM listening on php-fpm.sock
+    location ~ \.php$ {
+        try_files $uri =404;
+        fastcgi_split_path_info ^(.+\.php)(/.+)$;
+        fastcgi_pass unix:/run/php-fpm.sock;
+        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+        fastcgi_index index.php;
+        include fastcgi_params;
+    }
+
+    # Set the cache-control headers on assets to cache for 5 days
+    location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
+        expires 5d;
+    }
+
+    # Deny access to . files, for security
+    location ~ /\. {
+        log_not_found off;
+        deny all;
+    }
+
+    # Allow fpm ping and status from localhost
+    location ~ ^/(fpm-status|fpm-ping)$ {
+        access_log off;
+        allow 127.0.0.1;
+        deny all;
+        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+        include fastcgi_params;
+        fastcgi_pass unix:/run/php-fpm.sock;
+    }
+}
diff --git a/docker_config/fpm-pool.conf b/docker_config/fpm-pool.conf
new file mode 100644
index 0000000..4be2061
--- /dev/null
+++ b/docker_config/fpm-pool.conf
@@ -0,0 +1,56 @@
+[global]
+; Log to stderr
+error_log = /dev/stderr
+
+[www]
+; The address on which to accept FastCGI requests.
+; Valid syntaxes are:
+;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific IPv4 address on
+;                            a specific port;
+;   '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on
+;                            a specific port;
+;   'port'                 - to listen on a TCP socket to all addresses
+;                            (IPv6 and IPv4-mapped) on a specific port;
+;   '/path/to/unix/socket' - to listen on a unix socket.
+; Note: This value is mandatory.
+listen = /run/php-fpm.sock
+
+; Enable status page
+pm.status_path = /fpm-status
+
+; Ondemand process manager
+pm = ondemand
+
+; The number of child processes to be created when pm is set to 'static' and the
+; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'.
+; This value sets the limit on the number of simultaneous requests that will be
+; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
+; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
+; CGI. The below defaults are based on a server without much resources. Don't
+; forget to tweak pm.* to fit your needs.
+; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand'
+; Note: This value is mandatory.
+pm.max_children = 100
+
+; The number of seconds after which an idle process will be killed.
+; Note: Used only when pm is set to 'ondemand'
+; Default Value: 10s
+pm.process_idle_timeout = 10s;
+
+; The number of requests each child process should execute before respawning.
+; This can be useful to work around memory leaks in 3rd party libraries. For
+; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
+; Default Value: 0
+pm.max_requests = 1000
+
+; Make sure the FPM workers can reach the environment variables for configuration
+clear_env = no
+
+; Catch output from PHP
+catch_workers_output = yes
+
+; Remove the 'child 10 said into stderr' prefix in the log and only show the actual message
+decorate_workers_output = no
+
+; Enable ping page to use in healthcheck
+ping.path = /fpm-ping
diff --git a/docker_config/nginx.conf b/docker_config/nginx.conf
new file mode 100644
index 0000000..206334e
--- /dev/null
+++ b/docker_config/nginx.conf
@@ -0,0 +1,47 @@
+worker_processes auto;
+error_log stderr warn;
+pid /run/nginx.pid;
+
+events {
+    worker_connections 1024;
+}
+
+http {
+    include mime.types;
+    # Threat files with a unknown filetype as binary
+    default_type application/octet-stream;
+
+    # Define custom log format to include reponse times
+    log_format main_timed '$remote_addr - $remote_user [$time_local] "$request" '
+                          '$status $body_bytes_sent "$http_referer" '
+                          '"$http_user_agent" "$http_x_forwarded_for" '
+                          '$request_time $upstream_response_time $pipe $upstream_cache_status';
+
+    access_log /dev/stdout main_timed;
+    error_log /dev/stderr notice;
+
+    keepalive_timeout 65;
+
+    # Write temporary files to /tmp so they can be created as a non-privileged user
+    client_body_temp_path /tmp/client_temp;
+    proxy_temp_path /tmp/proxy_temp_path;
+    fastcgi_temp_path /tmp/fastcgi_temp;
+    uwsgi_temp_path /tmp/uwsgi_temp;
+    scgi_temp_path /tmp/scgi_temp;
+
+    # Hide headers that identify the server to prevent information leakage
+    proxy_hide_header X-Powered-By;
+    fastcgi_hide_header X-Powered-By;
+    server_tokens off;
+
+    # Enable gzip compression by default
+    gzip on;
+    gzip_proxied any;
+    # Based on CloudFlare's recommended settings
+    gzip_types text/richtext text/plain text/css text/x-script text/x-component text/x-java-source text/x-markdown application/javascript application/x-javascript text/javascript text/js image/x-icon image/vnd.microsoft.icon application/x-perl application/x-httpd-cgi text/xml application/xml application/rss+xml application/vnd.api+json application/x-protobuf application/json multipart/bag multipart/mixed application/xhtml+xml font/ttf font/otf font/x-woff image/svg+xml application/vnd.ms-fontobject application/ttf application/x-ttf application/otf application/x-otf application/truetype application/opentype application/x-opentype application/font-woff application/eot application/font application/font-sfnt application/wasm application/javascript-binast application/manifest+json application/ld+json application/graphql+json application/geo+json;
+    gzip_vary on;
+    gzip_disable "msie6";
+
+    # Include server configs
+    include /etc/nginx/conf.d/*.conf;
+}
diff --git a/docker_config/php.ini b/docker_config/php.ini
new file mode 100644
index 0000000..d85d12a
--- /dev/null
+++ b/docker_config/php.ini
@@ -0,0 +1,3 @@
+[Date]
+date.timezone="UTC"
+expose_php= Off
\ No newline at end of file
diff --git a/docker_config/supervisord.conf b/docker_config/supervisord.conf
new file mode 100644
index 0000000..26dabbe
--- /dev/null
+++ b/docker_config/supervisord.conf
@@ -0,0 +1,23 @@
+[supervisord]
+nodaemon=true
+logfile=/dev/null
+logfile_maxbytes=0
+pidfile=/run/supervisord.pid
+
+[program:php-fpm]
+command=php-fpm83 -F
+stdout_logfile=/dev/stdout
+stdout_logfile_maxbytes=0
+stderr_logfile=/dev/stderr
+stderr_logfile_maxbytes=0
+autorestart=false
+startretries=0
+
+[program:nginx]
+command=nginx -g 'daemon off;'
+stdout_logfile=/dev/stdout
+stdout_logfile_maxbytes=0
+stderr_logfile=/dev/stderr
+stderr_logfile_maxbytes=0
+autorestart=false
+startretries=0