Initial creation of image with php8.4-fpm with nginx
This commit is contained in:
66
.gitea/workflows/release.yml
Normal file
66
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
name: Build nginx fpm 8.4 image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
schedule:
|
||||||
|
# Run every Sunday at midnight
|
||||||
|
- cron: '0 0 * * 0'
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE: /docker/nginx-fpm-8-4
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Build-and-release-image:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
container:
|
||||||
|
image: catthehacker/ubuntu:act-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Log into registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ secrets.REGISTRY_URL }}
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASS }}
|
||||||
|
|
||||||
|
- name: Extract Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: ${{ secrets.REGISTRY_URL }}${{ env.IMAGE }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
env:
|
||||||
|
ACTIONS_RUNTIME_TOKEN: ''
|
||||||
|
with:
|
||||||
|
tags: ${{ secrets.REGISTRY_URL }}${{ env.IMAGE }}:latest
|
||||||
|
push: true
|
||||||
|
|
||||||
|
- name: Scan image
|
||||||
|
uses: anchore/scan-action@v6
|
||||||
|
id: scan
|
||||||
|
with:
|
||||||
|
image: ${{ secrets.REGISTRY_URL }}${{ env.IMAGE }}:latest
|
||||||
|
fail-build: false
|
||||||
|
output-format: table
|
||||||
|
severity-cutoff: critical
|
||||||
|
registry-username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
registry-password: ${{ secrets.REGISTRY_PASS }}
|
||||||
|
grype-version: 'v0.90.0'
|
||||||
|
|
||||||
|
- name: Inspect file
|
||||||
|
run: cat ${{ steps.scan.outputs.table }}
|
||||||
|
|
||||||
|
- name: Upload Artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: scan-result
|
||||||
|
path: ${{ steps.scan.outputs.table }}
|
||||||
|
|
||||||
60
Dockerfile
Normal file
60
Dockerfile
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
FROM alpine:3.21
|
||||||
|
LABEL Maintainer="Christian Steinle <kontakt@steinle-computer.de>"
|
||||||
|
LABEL Description="Lightweight container with Nginx 1.26 & PHP 8.4 based on Alpine Linux."
|
||||||
|
|
||||||
|
WORKDIR /var/www/html
|
||||||
|
|
||||||
|
# Set environment variable to serve not from /var/www/html but subpath, for e.g. Laravel.
|
||||||
|
ENV SERVE_PATH=
|
||||||
|
|
||||||
|
RUN apk update && \
|
||||||
|
apk upgrade && \
|
||||||
|
apk add --no-cache \
|
||||||
|
curl \
|
||||||
|
nginx \
|
||||||
|
php84 \
|
||||||
|
php84-bcmath \
|
||||||
|
php84-ctype \
|
||||||
|
php84-curl \
|
||||||
|
php84-dom \
|
||||||
|
php84-fileinfo \
|
||||||
|
php84-fpm \
|
||||||
|
php84-gd \
|
||||||
|
php84-mbstring \
|
||||||
|
php84-mysqli \
|
||||||
|
php84-openssl \
|
||||||
|
php84-pdo \
|
||||||
|
php84-pdo_mysql \
|
||||||
|
php84-pdo_pgsql \
|
||||||
|
php84-pdo_sqlite \
|
||||||
|
php84-session \
|
||||||
|
php84-tokenizer \
|
||||||
|
php84-xml \
|
||||||
|
php84-xsl \
|
||||||
|
php84-zip \
|
||||||
|
supervisor
|
||||||
|
|
||||||
|
# Link to php, for calling "php artisan serve".
|
||||||
|
RUN ln -s /usr/bin/php84 /usr/bin/php
|
||||||
|
|
||||||
|
# Copy configuration and entrypoint. Entrypoint is needed to change nginx's document root if environement variable is given.
|
||||||
|
COPY config/nginx.conf /etc/nginx/nginx.conf
|
||||||
|
COPY config/fpm-pool.conf /etc/php84/php-fpm.d/www.conf
|
||||||
|
COPY config/php.ini /etc/php84/conf.d/custom.ini
|
||||||
|
COPY config/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||||
|
COPY config/entrypoint.sh /bin/entrypoint.sh
|
||||||
|
|
||||||
|
RUN chmod a+x /bin/entrypoint.sh
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
RUN chown -R nobody:nobody /var/www/html /run /var/lib/nginx /var/log/nginx /etc/nginx
|
||||||
|
|
||||||
|
ENTRYPOINT ["/bin/entrypoint.sh"]
|
||||||
|
|
||||||
|
# Use unpriviledged user for security.
|
||||||
|
USER nobody
|
||||||
|
|
||||||
|
# Add healthcheck to container.
|
||||||
|
HEALTHCHECK --timeout=10s CMD curl --silent --fail http://127.0.0.1:8080/fpm-ping
|
||||||
|
|
||||||
9
README.md
Normal file
9
README.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Docker PHP-FPM & Nginx on Alpine Linux
|
||||||
|
|
||||||
|
* Built on the lightweight and secure Alpine Linux distribution
|
||||||
|
* Small image size
|
||||||
|
* PHP 8.4
|
||||||
|
* Optimized for 100 concurrent users
|
||||||
|
* Optimized to only use resources when there's traffic (PHP-FPM's on-demand process manager)
|
||||||
|
* Using a non-privileged user to make it more secure
|
||||||
|
* Logs of all services are redirected to the output of the container
|
||||||
7
config/entrypoint.sh
Executable file
7
config/entrypoint.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
sed -i "s|/var/www/html|/var/www/html${SERVE_PATH}|g" /etc/nginx/nginx.conf
|
||||||
|
|
||||||
|
/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
|
||||||
56
config/fpm-pool.conf
Normal file
56
config/fpm-pool.conf
Normal file
@@ -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
|
||||||
101
config/nginx.conf
Normal file
101
config/nginx.conf
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
worker_processes auto;
|
||||||
|
error_log stderr warn;
|
||||||
|
pid /run/nginx.pid;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include mime.types;
|
||||||
|
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;
|
||||||
|
|
||||||
|
# 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/html;
|
||||||
|
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_param SCRIPT_NAME $fastcgi_script_name;
|
||||||
|
fastcgi_index index.php;
|
||||||
|
include fastcgi_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Hardening
|
||||||
|
proxy_hide_header X-Powered-By;
|
||||||
|
fastcgi_hide_header X-Powered-By;
|
||||||
|
server_tokens off;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_proxied any;
|
||||||
|
gzip_types text/plain application/xml text/css text/js text/xml application/x-javascript text/javascript application/json application/xml+rss;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_disable "msie6";
|
||||||
|
|
||||||
|
# Include other server configs
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
}
|
||||||
4
config/php.ini
Normal file
4
config/php.ini
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[Date]
|
||||||
|
date.timezone="UTC"
|
||||||
|
expose_php=Off
|
||||||
|
|
||||||
25
config/supervisord.conf
Normal file
25
config/supervisord.conf
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
[supervisord]
|
||||||
|
nodaemon=true
|
||||||
|
user=nobody
|
||||||
|
logfile=/dev/null
|
||||||
|
logfile_maxbytes=0
|
||||||
|
pidfile=/run/supervisord.pid
|
||||||
|
|
||||||
|
[program:php-fpm]
|
||||||
|
command=php-fpm84 -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
|
||||||
|
|
||||||
Reference in New Issue
Block a user