Configuration Options Reference
Configuration Options Reference
Complete reference for advanced PHP, PHP-FPM, and Nginx configuration in Cbox base images.
Table of Contents
- PHP.ini Customization
- PHP-FPM Pool Configuration
- Nginx Server Blocks
- Custom Configuration Files
- Configuration Precedence
PHP.ini Customization
Method 1: Environment Variables (Recommended)
Use environment variables for simple settings (see Environment Variables Reference).
services:
app:
environment:
- PHP_MEMORY_LIMIT=256M
- PHP_MAX_EXECUTION_TIME=60
Method 2: Custom php.ini via Volume Mount
For complex configuration, mount a custom PHP configuration file.
Create docker/php/custom.ini:
[PHP]
; Memory & Execution
memory_limit = 512M
max_execution_time = 120
max_input_time = 120
; File Uploads
upload_max_filesize = 100M
post_max_size = 120M
max_file_uploads = 50
; Error Handling
display_errors = Off
display_startup_errors = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
log_errors = On
error_log = /proc/self/fd/2
; Date & Timezone
date.timezone = UTC
; Sessions
session.save_handler = redis
session.save_path = "tcp://redis:6379?database=2"
session.gc_maxlifetime = 7200
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = "Strict"
[opcache]
opcache.enable = 1
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
opcache.save_comments = 1
opcache.enable_file_override = 1
[apcu]
apc.enabled = 1
apc.shm_size = 128M
apc.ttl = 7200
apc.gc_ttl = 3600
Mount in docker-compose.yml:
services:
app:
image: ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.3-bookworm
volumes:
- ./:/var/www/html
- ./docker/php/custom.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
Filename Convention:
- Prefix with
zz-to ensure it loads last (alphabetical order) - Files in
conf.d/override previous settings - Use
.iniextension
Method 3: Dockerfile Extension
For permanent custom configuration in your image:
FROM ghcr.io/cboxdk/php-baseimages/php-fpm-nginx:8.3-bookworm
# Copy custom PHP configuration
COPY docker/php/custom.ini /usr/local/etc/php/conf.d/zz-custom.ini
Common PHP.ini Sections
Date & Time
[Date]
date.timezone = "America/New_York"
date.default_latitude = 40.7128
date.default_longitude = -74.0060
Security Settings
[Security]
; Disable dangerous functions
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
; Hide PHP version
expose_php = Off
; Restrict file access
open_basedir = /var/www/html:/tmp
; Session security
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = "Strict"
session.use_strict_mode = 1
Performance Tuning
[Performance]
; Realpath cache (speed up file lookups)
realpath_cache_size = 4M
realpath_cache_ttl = 600
; Output buffering
output_buffering = 4096
implicit_flush = Off
; Disable unused extensions
;extension=sodium ; Uncomment if not needed
PHP-FPM Pool Configuration
Method 1: Environment Variables (Basic)
Use environment variables for common settings:
services:
app:
environment:
- PHP_FPM_PM=dynamic
- PHP_FPM_PM_MAX_CHILDREN=50
- PHP_FPM_PM_START_SERVERS=10
Method 2: Custom Pool Configuration (Advanced)
Create docker/php-fpm/www.conf:
[www]
; Unix user/group of processes
user = www-data
group = www-data
; Process manager
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 1000
; Process timeout
request_terminate_timeout = 60s
; Slow request logging
request_slowlog_timeout = 5s
slowlog = /proc/self/fd/2
; Resource limits
rlimit_files = 4096
rlimit_core = 0
; Status page
pm.status_path = /fpm-status
; Ping page
ping.path = /fpm-ping
ping.response = pong
; Access log
access.log = /proc/self/fd/2
access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%"
; Security
security.limit_extensions = .php
; Environment variables
clear_env = no
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
; PHP.ini values (pool-specific)
php_admin_value[error_log] = /proc/self/fd/2
php_admin_flag[log_errors] = on
php_value[session.save_handler] = redis
php_value[session.save_path] = "tcp://redis:6379"
Mount in docker-compose.yml:
services:
app:
volumes:
- ./docker/php-fpm/www.conf:/usr/local/etc/php-fpm.d/zz-www.conf:ro
Multiple PHP-FPM Pools
Run different pools for different applications:
Create docker/php-fpm/api.conf:
[api]
user = www-data
group = www-data
listen = 127.0.0.1:9001
pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
request_terminate_timeout = 30s
php_value[memory_limit] = 128M
Update Nginx to route to different pools:
location /api {
fastcgi_pass 127.0.0.1:9001; # API pool
# ... other fastcgi settings
}
location / {
fastcgi_pass 127.0.0.1:9000; # Default pool
# ... other fastcgi settings
}
Nginx Server Blocks
Method 1: Custom Nginx Configuration via Volume
Create docker/nginx/default.conf:
server {
listen 80;
listen [::]:80;
server_name example.com;
root /var/www/html/public;
index index.php index.html;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/json application/javascript application/xml+rss
application/rss+xml application/atom+xml image/svg+xml
text/x-component text/x-cross-domain-policy;
# Client settings
client_max_body_size 100m;
client_body_timeout 60s;
# Logging
access_log /proc/self/fd/1;
error_log /proc/self/fd/2 warn;
# Default location
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Timeouts
fastcgi_read_timeout 60s;
fastcgi_send_timeout 60s;
fastcgi_connect_timeout 60s;
# Buffers
fastcgi_buffer_size 128k;
fastcgi_buffers 256 16k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
# Deny access to hidden files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Static files caching
location ~* \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
}
Mount in docker-compose.yml:
services:
app:
volumes:
- ./:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
Laravel-Specific Nginx Configuration
server {
listen 80;
server_name laravel.local;
root /var/www/html/public;
index index.php;
charset utf-8;
# Laravel public directory
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
# Deny access to .env files
location ~ /\.env {
deny all;
}
# Deny access to storage and bootstrap/cache
location ~ ^/(storage|bootstrap/cache) {
deny all;
}
# Allow Laravel Horizon dashboard
location /horizon {
try_files $uri $uri/ /index.php?$query_string;
}
error_page 404 /index.php;
}
Symfony-Specific Nginx Configuration
server {
listen 80;
server_name symfony.local;
root /var/www/html/public;
index index.php;
location / {
# Try to serve file directly, fallback to index.php
try_files $uri /index.php$is_args$args;
}
# DEV, PROD, and profiler
location ~ ^/(index|index_dev|config)\.php(/|$) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
internal;
}
# Return 404 for all other php files
location ~ \.php$ {
return 404;
}
}
WordPress-Specific Nginx Configuration
server {
listen 80;
server_name wordpress.local;
root /var/www/html;
index index.php;
# WordPress permalinks
location / {
try_files $uri $uri/ /index.php?$args;
}
# PHP-FPM
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Deny access to sensitive files
location ~ /\.(ht|git|svn) {
deny all;
}
location = /xmlrpc.php {
deny all;
access_log off;
}
# Static files caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# WordPress uploads
location ~* ^/wp-content/uploads/.*\.(php|php5|php7|phtml)$ {
deny all;
}
}
SSL/HTTPS Configuration
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
root /var/www/html/public;
# SSL certificates
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
# SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# ... rest of configuration
}
Custom Configuration Files
Directory Structure
project/
├── docker/
│ ├── php/
│ │ ├── custom.ini # PHP configuration
│ │ └── 99-custom.ini # Additional PHP settings
│ ├── php-fpm/
│ │ ├── www.conf # PHP-FPM pool
│ │ └── api.conf # Additional pool
│ └── nginx/
│ ├── default.conf # Main server block
│ ├── includes/
│ │ ├── security.conf # Security headers
│ │ └── gzip.conf # Compression settings
│ └── ssl/
│ ├── cert.pem
│ └── key.pem
├── docker-compose.yml
└── Dockerfile
docker-compose.yml with All Configs
version: '3.8'
services:
app:
build: .
ports:
- "443:443"
- "80:80"
volumes:
# Application code
- ./:/var/www/html
# PHP configuration
- ./docker/php/custom.ini:/usr/local/etc/php/conf.d/zz-custom.ini:ro
- ./docker/php/99-custom.ini:/usr/local/etc/php/conf.d/zz-99-custom.ini:ro
# PHP-FPM configuration
- ./docker/php-fpm/www.conf:/usr/local/etc/php-fpm.d/zz-www.conf:ro
- ./docker/php-fpm/api.conf:/usr/local/etc/php-fpm.d/zz-api.conf:ro
# Nginx configuration
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./docker/nginx/includes/:/etc/nginx/includes/:ro
- ./docker/nginx/ssl/:/etc/nginx/ssl/:ro
environment:
- PHP_MEMORY_LIMIT=512M
Nginx Include Files
docker/nginx/includes/security.conf:
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
docker/nginx/includes/gzip.conf:
# Gzip compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 256;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/json
application/javascript
application/xml+rss
application/rss+xml
application/atom+xml
image/svg+xml
text/x-component
text/x-cross-domain-policy;
Use in main nginx config:
server {
listen 80;
# ... other settings
# Include security headers
include /etc/nginx/includes/security.conf;
# Include compression settings
include /etc/nginx/includes/gzip.conf;
}
Configuration Precedence
PHP Configuration Loading Order
- Built-in defaults (
/usr/local/etc/php/php.ini-production) - Additional .ini files (alphabetically from
/usr/local/etc/php/conf.d/)docker-php-ext-*.ini(extensions)zz-custom.ini(your overrides)
- PHP-FPM pool directives (
php_value,php_admin_value) - Runtime (
.htaccess,ini_set())
Example precedence:
php.ini: memory_limit = 128M
zz-custom.ini: memory_limit = 256M ← Overrides php.ini
php-fpm pool: memory_limit = 512M ← Overrides zz-custom.ini
Verification Commands
# Check which php.ini is loaded
docker exec <container> php --ini
# Check specific setting
docker exec <container> php -r "echo ini_get('memory_limit');"
# Check all settings
docker exec <container> php -i | grep memory_limit
# Check PHP-FPM pool config
docker exec <container> cat /usr/local/etc/php-fpm.d/www.conf
# Check Nginx config syntax
docker exec <container> nginx -t
# Check active Nginx config
docker exec <container> cat /etc/nginx/conf.d/default.conf
Testing Configuration Changes
1. Test Locally First
# Build with new config
docker-compose build
# Start container
docker-compose up -d
# Check logs for errors
docker-compose logs -f
# Verify settings
docker exec $(docker-compose ps -q app) php -i | grep memory_limit
2. Test Nginx Configuration
# Test Nginx syntax
docker exec <container> nginx -t
# Reload Nginx (no downtime)
docker exec <container> nginx -s reload
3. Test PHP-FPM Configuration
# Test PHP-FPM config
docker exec <container> php-fpm -t
# Reload PHP-FPM (graceful)
docker exec <container> kill -USR2 1
Common Configuration Patterns
High Traffic Configuration
# PHP
memory_limit = 512M
max_execution_time = 30
# OPcache
opcache.memory_consumption = 512
opcache.max_accelerated_files = 50000
opcache.validate_timestamps = 0
# PHP-FPM
pm = static
pm.max_children = 100
pm.max_requests = 1000
Development Configuration
# PHP
display_errors = On
error_reporting = E_ALL
opcache.validate_timestamps = 1
opcache.revalidate_freq = 0
# PHP-FPM
pm = dynamic
pm.max_children = 10
request_slowlog_timeout = 1s
Memory-Constrained Configuration
# PHP
memory_limit = 128M
# OPcache
opcache.memory_consumption = 64
# PHP-FPM
pm = ondemand
pm.max_children = 20
pm.process_idle_timeout = 10s
Related Documentation
- Environment Variables Reference - Simple configuration via env vars
- Performance Tuning - Optimization strategies
- Security Hardening - Security best practices
- Extending Images - Creating custom images
Questions? Check common issues or ask in GitHub Discussions.