diff --git a/docs/docker.md b/docs/docker.md index 23af3fa027..cd57dcd3c0 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -35,6 +35,69 @@ docker run -it --rm --name my-running-app my-php-app For convenience, [a default `Caddyfile`](https://github.com/php/frankenphp/blob/main/caddy/frankenphp/Caddyfile) containing useful environment variables is provided in the image. +## ⚠️ Important: Required Caddy storage directories inside Docker + +When running FrankenPHP inside Docker, Caddy uses two internal storage directories: + +- `/data/caddy` for the certificates, locks, cache +- `/config/caddy` for the autosave file (`autosave.json`) + +These directories are **not created automatically**. + +If `/config/caddy` does not exist or is not writable, Caddy will fail to save its adapted configuration and will silently fall back to: +``` +serving initial configuration +``` + +even if your `Caddyfile` is valid. + +### Recommended fix (Dockerfile) + +Add the following snippet to your Dockerfile **before switching to `www-data`**: + +```dockerfile +RUN mkdir -p /data/caddy/locks \ + && mkdir -p /config/caddy \ + && touch /data/caddy/instance.uuid \ + && chown -R www-data:www-data /data /config /etc/caddy +``` + +## Using Docker Compose: important note about the application directory + +When using Docker Compose with bind-mounted volumes (e.g. .:/app), Docker mounts the volume after the container starts. + +Caddy validates the root directive before the mount happens. + +If your application is mounted over /app, this overwrites internal Caddy files and may prevent it from accessing: + ``` +- /etc/caddy/Caddyfile +- /data/caddy +- /config/caddy +``` +This results in Caddy failing validation and falling back to the initial configuration, even if everything else is correct. + +## Recommendation for Docker Compose users + +Do not mount your application into `/app`. + +Instead, use a dedicated directory such as: `/srv/app` + + +Example: +``` +services: + app: + volumes: + - .:/srv/app +``` + +And ensure the root directory exists in the image: +``` +RUN mkdir -p /srv/app/public +``` +This prevents the bind-mount from overwriting internal Caddy directories and guarantees stable behavior during development. +This setup matches the directory structure used in many production deployments and avoids subtle issues with Caddy startup sequencing. + ## How to Install More PHP Extensions The [`docker-php-extension-installer`](https://github.com/mlocati/docker-php-extension-installer) script is provided in the base image. diff --git a/docs/worker.md b/docs/worker.md index e055436d30..873bce661d 100644 --- a/docs/worker.md +++ b/docs/worker.md @@ -163,6 +163,24 @@ frankenphp { } ``` +## Memory Management + +The PHP `memory_limit` directive applies per worker. If a worker exceeds the memory limit while handling a request, it will be automatically restarted and an error will be logged. + +You can use `ini_set('memory_limit', '512M')` to change the limit dynamically during a request. The limit is automatically reset to the value defined in `php.ini` after each request is handled. + +When running in Docker, make sure to account for all workers when setting the container memory limit. As a rule of thumb, `num_threads` x `memory_limit` should be lower than the available memory (see [Performance](performance.md#number-of-threads-and-workers) for details). + +You can configure `memory_limit` directly in your `Caddyfile` using the `php_ini` directive (see [PHP config](config.md#php-config)): + +```caddyfile +{ + frankenphp { + php_ini memory_limit 256M + } +} +``` + ## Superglobals Behavior [PHP superglobals](https://www.php.net/manual/en/language.variables.superglobals.php) (`$_SERVER`, `$_ENV`, `$_GET`...)