Use this image instead of the normal php-8.3-fpm-alpine.
It's the same except with a custom configuration more suitable for production use.
The image is rebuilt automatically whenever a new version of the original php
image is pushed.
Replace php:8.3-fpm-alpine
in your docker-compose.yml
file with ghcr.io/deltablot/php-prod:8.3
.
Use ghcr.io/deltablot/php-prod
as base image and docker-php-ext-install
to install the required extensions.
Example with mysqli
is present in this repository: Dockerfile.mysqli.
You should have a running nginx serving your files already.
In the nginx config file:
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html/your-code$fastcgi_script_name;
}
Adjust the path to where your code exists (and it will depend on how you mount the volumes of course).
The websites are mounted in /sites
in the (read-only) nginx container, and the local nginx/sites
folder contain folders of the websites source files. The local nginx/conf
folder contains the nginx config files.
# NGINX
nginx:
image: nginx:1.26-alpine
container_name: nginx
restart: always
read_only: true
depends_on:
- php
expose:
- '80'
volumes:
- ./nginx/conf:/etc/nginx:ro
- ./nginx/sites:/sites:ro
networks:
- your-net
# PHP
php:
image: ghcr.io/deltablot/php-prod:8.3
build:
context: ./php-prod
dockerfile: Dockerfile.mysqli
expose:
- '9000'
# if hosting several sites, add them as volume here
volumes:
- ./nginx/sites/your-site:/var/www/html/your-site
networks:
- your-net
Sessions are moved to a dedicated directory with strict permissions.
Use strict mode and longer id length.
Force httponly and secure flag for cookies.
- Don't expose PHP version
- Make sure only PHP files are processed
- Disallow
url_fopen
Based on https://dev.to/elabftw/10-steps-for-securing-a-php-app-5fnp.
git clone https://github.com/deltablot/php-prod
cd php-prod
docker build -t deltablot/php-prod .
MIT. See LICENSE file.