Files
nginx-php-fpm/README.md
T
jkaninda 5abd5bc076
Tests / integration (8.2, alpine) (push) Canceled after 0s
Tests / integration (8.2, debian) (push) Canceled after 0s
Tests / integration (8.3, alpine) (push) Canceled after 0s
Tests / integration (8.3, debian) (push) Canceled after 0s
Tests / integration (8.4, alpine) (push) Canceled after 0s
Tests / integration (8.4, debian) (push) Canceled after 0s
Tests / integration (8.5, alpine) (push) Canceled after 0s
Tests / integration (8.5, debian) (push) Canceled after 0s
Modernize images and move PHP 8.1 to legacy
PHP 8.1 is end-of-life. It is dropped from the default build and test
matrices. 8.1 and 8.1-alpine are still built, multi-arch, by the
manual legacy job (workflow_dispatch with legacy=true), together with
7.2, 7.3, 7.4 and 8.0. This replaces manual-build.yml.
2026-10-22 05:30:34 +02:00

320 lines
9.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### 🐳 **Docker Image: Nginx PHP-FPM**
A **ready-to-use container** designed for running PHP-based applications, including Laravel microservices. This Docker image combines **Nginx** and **PHP-FPM**, offering a robust foundation for your projects with built-in support for essential extensions and configurations.
[![Build](https://github.com/jkaninda/nginx-php-fpm/actions/workflows/build.yml/badge.svg)](https://github.com/jkaninda/nginx-php-fpm/actions/workflows/build.yml)
[![Tests](https://github.com/jkaninda/nginx-php-fpm/actions/workflows/tests.yml/badge.svg)](https://github.com/jkaninda/nginx-php-fpm/actions/workflows/tests.yml)
![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/jkaninda/nginx-php-fpm?style=flat-square)
![Docker Pulls](https://img.shields.io/docker/pulls/jkaninda/nginx-php-fpm?style=flat-square)
#### **Features**
- **PHP Application Support**: Optimized to run Laravel or any PHP-based applications.
- **Nginx and PHP-FPM in one container**, managed by Supervisord.
- **Integrated Extensions**:
- **Database**: MySQL and PostgreSQL.
- **Caching**: Redis and Memcached.
- **Messaging**: Kafka for event-driven architecture.
- **Task Scheduling**: Laravel Scheduler and Queue Worker started automatically.
- **Custom Configuration**: Pre-configured with sensible defaults, tunable through environment variables.
- **Debian and Alpine variants**, multi-arch (`linux/amd64`, `linux/arm64`).
- **Production-ready**: healthcheck, graceful shutdown, OPcache, logs on stdout, `supervisorctl` support.
- **Optimized for Microservices**: Built with modern PHP microservices in mind.
This image is ideal for developers looking for a streamlined, high-performance solution to deploy PHP applications with essential tools already integrated.
---
## **Links**
- [Docker Hub](https://hub.docker.com/r/jkaninda/nginx-php-fpm)
- [GitHub Repository](https://github.com/jkaninda/nginx-php-fpm)
## **Supported PHP Versions & Tags**
| PHP | Debian tag | Alpine tag |
|-----|------------|------------|
| 8.5 | `8.5`, `latest` | `8.5-alpine`, `alpine` |
| 8.4 | `8.4` | `8.4-alpine` |
| 8.3 | `8.3` | `8.3-alpine` |
| 8.2 | `8.2` | `8.2-alpine` |
Legacy images (PHP is end-of-life, no longer rebuilt automatically or tested): `8.1`, `8.1-alpine`, `8.0`, `7.4`, `7.3`, `7.2`.
---
## **Specifications**
### **PHP Extensions**
- Composer 2
- OpenSSL
- XML
- PDO (MySQL, PostgreSQL and SQLite)
- Rdkafka
- Redis
- Mbstring
- Intl
- Exif
- PCNTL
- ZIP
- GD (FreeType, JPEG, PNG, WebP)
- BCMath
- Memcached
- Opcache
### **Additional Features**
- Nginx
- Laravel Scheduler
- Laravel Queue Worker
- Supervisord
- Node.js 24 LTS and NPM
- Git, Zip/Unzip, SQLite CLI
---
## **Basic Usage with Docker Compose**
### **Example `docker-compose.yml`**
```yaml
services:
app:
image: jkaninda/nginx-php-fpm:8.5
container_name: app
restart: unless-stopped
volumes:
# Project root
- ./src:/var/www/html
ports:
- "80:80"
```
### **Commands**
#### Start the service:
```sh
docker compose up -d
```
#### Create a new Laravel project:
```sh
docker compose exec -u www-data app composer create-project --prefer-dist laravel/laravel .
```
#### Generate application key:
```sh
docker compose exec -u www-data app php artisan key:generate
```
#### Create a storage symlink:
```sh
docker compose exec -u www-data app php artisan storage:link
```
#### Fix storage and cache permissions:
```sh
docker compose exec app chown -R www-data:www-data storage bootstrap/cache
```
#### Run Laravel migrations:
```sh
docker compose exec -u www-data app php artisan migrate
```
#### Access the container shell:
```sh
docker exec -it app bash
```
#### Run a one-off command (Nginx and PHP-FPM are not started):
```sh
docker run --rm -v "$PWD:/var/www/html" jkaninda/nginx-php-fpm composer install
```
#### Restart the queue workers after a deployment:
```sh
docker compose exec app supervisorctl restart Laravel-worker:*
```
---
## **Environment Variables**
### Nginx
| Variable | Default | Description |
|----------|---------|-------------|
| `DOCUMENT_ROOT` | `$APP_DIR/public` if it exists, otherwise `$APP_DIR` | Nginx web root |
| `DOMAIN` | `_` | Nginx `server_name` |
| `CLIENT_MAX_BODY_SIZE` | `15M` | Nginx `client_max_body_size` |
### Laravel
| Variable | Default | Description |
|----------|---------|-------------|
| `LARAVEL_SCHEDULER_ENABLED` | `true` | Run `php artisan schedule:run` every minute |
| `LARAVEL_QUEUE_WORKER_ENABLED` | `true` | Run `php artisan queue:work` |
| `LARAVEL_QUEUE_OPTIONS` | `--sleep=3 --tries=3` | Options passed to `queue:work` (e.g. `redis --queue=high,default`) |
| `LARAVEL_PROCS_NUMBER` | `1` | Number of queue worker processes |
| `APP_DIR` | `/var/www/html` | Application directory (where `artisan` is looked up) |
The scheduler and queue worker are only started when an `artisan` file is found in `APP_DIR`.
### PHP
| Variable | Default |
|----------|---------|
| `PHP_MEMORY_LIMIT` | `256M` |
| `PHP_UPLOAD_MAX_FILESIZE` | `80M` |
| `PHP_POST_MAX_SIZE` | `80M` |
| `PHP_MAX_EXECUTION_TIME` | `30` |
| `PHP_DATE_TIMEZONE` | `UTC` |
| `PHP_DISPLAY_ERRORS` | `Off` |
### OPcache
| Variable | Default | Description |
|----------|---------|-------------|
| `PHP_OPCACHE_ENABLE` | `1` | |
| `PHP_OPCACHE_ENABLE_CLI` | `0` | |
| `PHP_OPCACHE_MEMORY_CONSUMPTION` | `512` | MB |
| `PHP_OPCACHE_MAX_ACCELERATED_FILES` | `50000` | |
| `PHP_OPCACHE_VALIDATE_TIMESTAMPS` | `0` | Set to `1` in development so code changes are picked up |
| `PHP_OPCACHE_REVALIDATE_FREQ` | `0` | |
### PHP-FPM
| Variable | Default |
|----------|---------|
| `PHP_FPM_PM` | `dynamic` |
| `PHP_FPM_PM_MAX_CHILDREN` | `20` |
| `PHP_FPM_PM_START_SERVERS` | `2` |
| `PHP_FPM_PM_MIN_SPARE_SERVERS` | `1` |
| `PHP_FPM_PM_MAX_SPARE_SERVERS` | `3` |
| `PHP_FPM_PM_MAX_REQUESTS` | `500` |
Container environment variables (e.g. `DB_HOST`, `APP_KEY`) are passed to PHP-FPM workers (`clear_env = no`).
### Development example
```yaml
services:
app:
image: jkaninda/nginx-php-fpm:8.5
ports:
- "80:80"
environment:
PHP_OPCACHE_VALIDATE_TIMESTAMPS: 1
PHP_DISPLAY_ERRORS: "On"
CLIENT_MAX_BODY_SIZE: 20M
LARAVEL_QUEUE_OPTIONS: "redis --sleep=3 --tries=3"
LARAVEL_PROCS_NUMBER: 2
volumes:
- ./:/var/www/html
```
---
## **Custom Build Example**
### **Dockerfile**
```Dockerfile
FROM jkaninda/nginx-php-fpm:8.5
# Copy Laravel project files
COPY . /var/www/html
# Storage Volume
VOLUME /var/www/html/storage
WORKDIR /var/www/html
# Fix permissions
RUN chown -R www-data:www-data /var/www/html
```
---
## **Custom Nginx Configuration**
To use custom Nginx configurations, add the following files to your project:
- `conf/nginx/nginx.conf`: replaces `/etc/nginx/nginx.conf`
- `conf/nginx/nginx-site.conf`: replaces the generated server block. PHP-FPM listens on `127.0.0.1:9000`.
---
## **Custom PHP Configuration**
Most common settings can be changed with [environment variables](#environment-variables).
For anything else, either:
- mount or copy your own `.ini` file into `/usr/local/etc/php/conf.d/`, or
- place a `php.ini` file at `conf/php/php.ini` in your project; it is copied into `conf.d` at startup.
---
## **Supervisord Integration**
Supervisord can be used to manage tasks or processes within the container.
Place your programs in `conf/worker/supervisor.conf` in your project, or mount them into `/etc/supervisor/conf.d/`.
### **Example Configuration for Kafka Consumer**
```conf
[program:kafkaconsume-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan kafka:consumer
autostart=true
autorestart=true
numprocs=1
user=www-data
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/kafka.log
```
---
## **Fixing Storage Permissions**
`www-data` has UID/GID `1000` in both Debian and Alpine variants. If you encounter permission issues, run:
```sh
docker compose exec app chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache
docker compose exec app chmod -R 775 /var/www/html/storage
```
To match your host user, rebuild with `--build-arg USER_ID=$(id -u) --build-arg GROUP_ID=$(id -g)`.
---
## **Building & Testing Locally**
```sh
make build-8.5 # Debian image
make build-8.5-alpine # Alpine image
make test # Integration test (Laravel + MySQL)
```
---
### Explore Another Project: Goma Gateway
Are you building a microservices architecture?
Do you need a powerful yet lightweight API Gateway or a high-performance reverse proxy to secure and manage your services effortlessly?
Check out my other project — **[Goma Gateway](https://github.com/jkaninda/goma-gateway)**.
**Goma Gateway** is a high-performance, declarative API Gateway built for modern microservices. It comes with a rich set of built-in middleware, including:
* Basic, JWT, OAuth2, LDAP, and ForwardAuth authentication
* Caching and rate limiting
* Bot detection
* Built-in load balancing
* Simple configuration with minimal overhead
* ...and more!
**Protocol support:** REST, GraphQL, gRPC, TCP, and UDP
**Security:** Automatic HTTPS via Let’s Encrypt or use your own TLS certificates
Whether you're managing internal APIs or exposing public endpoints, **Goma Gateway** helps you do it efficiently, securely, and with minimal complexity.
---
## ⭐️ **Support the Project**
If this project helped you, do not skip on giving it a star. Thanks!