php-nginx
adamrollogi/php-nginx:{version} adds Nginx 1.30 and PHP-FPM on top of the php image. Mount your application at /var/www/html and it is served immediately.
Quick start
docker run --rm -d -p 8080:8080 \
-e NGINX_PORT=8080 \
-v $(pwd)/public:/var/www/html:ro \
adamrollogi/php-nginx:8.4
Ports 80 and 443 are exposed but, because the container runs as UID 1000 by default, you bind to 8080 and 8443 unless you run with --user root. See Users and permissions.
What you get out of the box
- Health endpoint.
GET /healthreturns200 OKwith the security headers and is used by the image's ownHEALTHCHECK. - Security headers.
X-Frame-Options,X-Content-Type-Options,Referrer-PolicyandPermissions-Policyon every response, plus HSTS when HTTPS is on. - Hidden files denied. Anything under a dot-prefixed path (
/.env,/.git/...) returns 403, except/.well-known/, which is served for ACME challenges. - Safe PHP handling.
cgi.fix_pathinfo=0andsecurity.limit_extensions=.php, so/image.png/evil.phpstyle attacks fail. - Sensible limits.
client_max_body_sizefollowsPHP_POST_MAX_SIZE; 60-second timeouts; gzip for text assets. - No surprises on the default page. Without a volume you get a static one-line placeholder, never
phpinfo(). - IPv4 and IPv6 listeners, with
NGINX_LISTEN_IPV6=falsefor hosts that disable IPv6. - Tagged logs for
[nginx],[php-fpm],[entrypoint]and, in root mode,[cron].
Process model
| Mode | How it runs | Users |
|---|---|---|
| Non-root (default) | The entrypoint starts PHP-FPM and Nginx directly and waits on both. No cron. | Everything as appuser (UID 1000). |
Root (--user root) | Supervisor manages cron, Nginx and PHP-FPM. | Nginx workers as nginx, FPM workers as nobody, masters and cron as root. |
Either way, every service is started through run-service, so its log lines carry the service name.
Configuration
Everything is an environment variable. The pages below cover each area in depth; this is the shape of it.
| Area | Key variables | Page |
|---|---|---|
| PHP | PHP_MEMORY_LIMIT, PHP_POST_MAX_SIZE, php.<setting> | PHP settings |
| PHP-FPM | PHP_FPM_MAX_CHILDREN, PHP_FPM_LISTEN, fpm.pool.<setting> | PHP settings |
| Nginx | NGINX_PORT, NGINX_SERVER_NAME, NGINX_DOCUMENT_ROOT | Nginx |
| HTTPS | NGINX_SSL_ENABLED, NGINX_SSL_SELF_SIGNED, NGINX_SSL_REDIRECT_HOST | SSL and HTTPS |
| Logging | LOG_MODE, LOG_FORMAT, NGINX_ACCESS_LOG | Logging |
Drop-in configuration
For anything the variables do not cover, mount or COPY files into these directories. They are read at startup and stay root-owned.
| Directory | Scope | Typical use |
|---|---|---|
/etc/nginx/http-conf.d/*.conf | http block | map, upstream, log_format, rate-limit zones |
/etc/nginx/after.d/*.conf | inside the app server block | extra location blocks, rewrites, headers |
/etc/nginx/http.d/*.conf | additional server blocks | a second vhost on another port |
Layout
| Path | Purpose |
|---|---|
/var/www/html | Document root (NGINX_DOCUMENT_ROOT). |
/usr/local/etc/nginx/*.template | Nginx server block templates (HTTP, HTTPS, redirect). Root-owned. |
/usr/local/etc/php/www.conf.template | PHP-FPM pool template. |
/run/nginx/nginx.conf | Rendered main config, derived from the stock /etc/nginx/nginx.conf. |
/run/nginx/http.d/*.conf | Rendered server blocks. |
/run/nginx/logging.conf | json_combined log format definition. |
/run/php/php.ini, /run/php/php-fpm.conf, /run/php/php-fpm.d/www.conf | Rendered PHP and FPM config. |
/etc/nginx/ssl/ | Default certificate location, writable so self-signed certificates can be generated. |
/usr/local/bin/php-nginx-entrypoint.sh | Entrypoint. |
/usr/local/bin/healthcheck.sh | HEALTHCHECK command; always probes /health on the right port and scheme. |
Nginx is started with -c /run/nginx/nginx.conf and PHP-FPM with -y /run/php/php-fpm.conf -c /run/php/php.ini, which is what keeps /etc read-only to the runtime user.