Production-grade PHP 8.4 + Nginx + Redis stack for modern web applications
Features β’ Quick Start β’ Documentation β’ Makefile Commands β’ Docker Compose
- π PHP 8.4 with OPcache JIT (tracing mode) for maximum performance
- β‘ Nginx 1.27.3 optimized for high-throughput APIs
- π΄ Redis 7.2 for caching and session management
- π― Production-ready with security hardening and performance tuning
- π Comprehensive health checks for monitoring and orchestration
- π οΈ Developer-friendly with extensive Make targets (50+) and examples
- π Security-first with rate limiting, headers, and vulnerability scanning
- π¦ Multi-platform support (amd64, arm64)
- π Flexible deployment via Docker or Docker Compose with profiles
- π§° Three specialized Makefiles for building, Docker Hub, and Compose operations
# Pull and run with demo page
docker pull kariricode/php-api-stack:latest
docker run -d -p 8080:80 --name my-api kariricode/php-api-stack:latest
# Access the demo
curl http://localhost:8080
# or open http://localhost:8080 in browserdocker run -d \
-p 8080:80 \
-v $(pwd)/app:/var/www/html \
-v $(pwd)/.env:/var/www/html/.env:ro \
-e APP_ENV=production \
--name my-api \
kariricode/php-api-stack:latest# Setup
cp .env.example .env
cp docker-compose.example.yml docker-compose.yml
# Start base services
make compose-up
# Start with database + monitoring
make compose-up PROFILES="db,monitoring"
# Or start everything
make compose-up-all
# Access
open http://localhost:8089 # Application
open http://localhost:8089/health # Health check
open http://localhost:3000 # Grafana (admin/password)π See DOCKER_COMPOSE_GUIDE.md for complete Docker Compose documentation
| Document | Audience | Description |
|---|---|---|
| IMAGE_USAGE_GUIDE.md | End Users | How to use the published Docker image |
| DOCKER_COMPOSE_GUIDE.md | Developers | Complete Docker Compose orchestration guide |
| TESTING.md | Maintainers | Comprehensive testing procedures |
| DOCKER_HUB.md | Publishers | Docker Hub publication workflow |
βββββββββββββββββββββββββββββββββββ
β Client Request β
βββββββββββββββ¬ββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββ
β Nginx (port 80) β
β β’ FastCGI Cache β
β β’ Rate Limiting β
β β’ Security Headers β
βββββββββββββββ¬ββββββββββββββββββββ
β Unix Socket
βββββββββββββββΌββββββββββββββββββββ
β PHP-FPM 8.4 β
β β’ OPcache + JIT β
β β’ Pool Manager (60 children) β
βββββββββββββββ¬ββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββ
β PHP Application β
β β’ Framework (Symfony/Laravel) β
β β’ Business Logic β
βββββββββββββββ¬ββββββββββββββββββββ
β
βββββββββββββββΌββββββββββββββββββββ
β Redis (sessions/cache) β
β β’ AOF Persistence β
β β’ LRU Eviction β
βββββββββββββββββββββββββββββββββββ
Container Management: All services orchestrated by custom entrypoint with health monitoring and graceful shutdown
| Component | Version | Purpose | Configuration |
|---|---|---|---|
| PHP-FPM | 8.4.13 | PHP processing | Optimized pool, OPcache JIT |
| Nginx | 1.27.3 | Web server | FastCGI cache, rate limiting |
| Redis | 7.2.11 | Cache & sessions | AOF persistence, LRU eviction |
| Composer | 2.8.12 | Dependency manager | Included in production |
| Symfony CLI | 5.15.1 | Symfony tools | Dev image only |
| Xdebug | 3.4.6 | PHP debugger | Dev image only (optional) |
pdo, pdo_mysql, opcache, intl, zip, bcmath, gd, mbstring, xml, sockets
redis (6.1.0), apcu (5.1.24), uuid (1.2.1), imagick (3.7.0), amqp (2.1.2)
json, curl, fileinfo, ctype, iconv, session, tokenizer, filter, hash, openssl
Edit .env before building:
# Add your extension to the list
PHP_CORE_EXTENSIONS="pdo pdo_mysql opcache intl zip bcmath gd mbstring xml sockets mysqli"
PHP_PECL_EXTENSIONS="redis apcu uuid xdebug"
# Rebuild
make buildNote: For production images, extensions are optimized and loaded automatically.
All configuration is managed via .env file with extensive customization options:
# Environment
APP_ENV=production # production|development|test
APP_DEBUG=false # Enable debug mode (dev only)
# PHP Performance
PHP_MEMORY_LIMIT=256M # Memory limit per request
PHP_MAX_EXECUTION_TIME=60 # Script timeout
PHP_OPCACHE_MEMORY=256 # OPcache memory (MB)
PHP_OPCACHE_JIT=tracing # JIT mode: off|tracing|function
PHP_OPCACHE_ENABLE=1 # Enable OPcache (always 1 in prod)
# PHP-FPM Pool
PHP_FPM_PM=dynamic # Process manager mode
PHP_FPM_PM_MAX_CHILDREN=60 # Max child processes
PHP_FPM_PM_START_SERVERS=10 # Initial servers
PHP_FPM_PM_MIN_SPARE_SERVERS=5 # Min idle servers
PHP_FPM_PM_MAX_SPARE_SERVERS=20 # Max idle servers
# Redis
REDIS_HOST=127.0.0.1 # Redis host (standalone mode)
REDIS_PASSWORD=your-secure-password # Redis authentication
REDIS_DATABASES=16 # Number of databases
REDIS_MAXMEMORY=256mb # Max memory usage
REDIS_MAXMEMORY_POLICY=allkeys-lru # Eviction policy
# Nginx
NGINX_WORKER_PROCESSES=auto # Worker processes (auto = CPU cores)
NGINX_WORKER_CONNECTIONS=2048 # Connections per worker
NGINX_KEEPALIVE_TIMEOUT=65 # Keep-alive timeout
NGINX_CLIENT_MAX_BODY_SIZE=20M # Max upload sizeAPP_ENV=development
APP_DEBUG=true
PHP_DISPLAY_ERRORS=On
PHP_OPCACHE_VALIDATE_TIMESTAMPS=1 # Reload PHP files without restart
XDEBUG_ENABLE=1 # Enable XdebugFull reference: Copy .env.example and customize for your needs.
The project includes three specialized Makefiles for different purposes:
| Makefile | Purpose | Commands |
|---|---|---|
| Makefile | Build, test, run containers | 40+ commands |
| Makefile.dockerhub | Docker Hub operations | Version management, tagging, push, release |
| Makefile.compose | Docker Compose orchestration | Multi-service management |
Run make help for the main menu, or specialized help:
make hub-help- Docker Hub commandsmake compose-help- Docker Compose commands
make build # Build production image (optimized)
make build-dev # Build dev image (Symfony CLI + optional Xdebug)
make build-base # Build base layer only (for debugging)
make build-test # Build test image with comprehensive health check
make build-all # Build both production and dev images
make lint # Lint Dockerfile with hadolint
make scan # Security scan with Trivy
make scan-dev # Scan dev image for vulnerabilitiesmake run # Run production container (port 8080)
make run-dev # Run dev container (port 8001, Xdebug on 9003)
make run-test # Run test container with health monitoringmake stop # Stop production container
make stop-dev # Stop dev container
make stop-test # Stop test container
make restart # Restart production container
make restart-dev # Restart dev containermake logs # Follow production logs
make logs-dev # Follow dev logs
make shell # Open shell in production container
make shell-dev # Open shell in dev containermake test # Run comprehensive test suite
make test-quick # Quick component version checks
make test-structure # Validate container structure
make test-health # Test health check endpointThese commands are in Makefile.dockerhub. Run make hub-help for complete list.
make version # Show current version
make bump-patch # Bump patch (1.5.0 β 1.5.1)
make bump-minor # Bump minor (1.5.0 β 1.6.0)
make bump-major # Bump major (1.5.0 β 2.0.0)make tag-production # Tag production image (latest, 1, 1.5, 1.5.0)
make tag-dev # Tag dev image (dev only)
make push-production # Push all production tags
make push-dev # Push dev tag
make push-all # Push all imagesmake publish-production # Build + Tag + Push production
make publish-dev # Build + Tag + Push dev
make release-production # Full release: pre-check + build + test + scan + push
make release-all # Release both production and devmake hub-check # Check if images exist on Docker Hub
make hub-tags # List all published tags
make hub-info # Show repository information
make hub-clean # Remove old local tags
make pre-release-check # Validate before release (git, docker, auth)Example Release Workflow:
make bump-minor # 1.5.0 β 1.6.0
make release-production # Full automated releaseThese commands are in Makefile.compose. Run make compose-help for complete list.
make compose-up # Start services (respects PROFILES)
make compose-up-all # Start with all profiles
make compose-down-v # Stop and remove volumes
make compose-down-all # Stop everything + all profiles
make compose-restart # Restart services
make compose-ps # Show service statusmake compose-logs # Tail logs (all active services)
make compose-logs-all # Tail logs (base + all profiles)
make compose-logs-svc # Tail logs for specific services
make compose-shell # Open shell in service
make compose-exec # Execute command in servicemake compose-config # Show resolved config
make compose-health # Test health endpoint
make compose-open # Open app/Prometheus/Grafana in browserExample with Profiles:
# Start with database
make compose-up PROFILES="db"
# Start with monitoring
make compose-up PROFILES="monitoring"
# Start specific services
make compose-up-svc SERVICES="php-api-stack mysql"
# View specific logs
make compose-logs-svc SERVICES="php-api-stack"Development Workflow:
make build-dev # Build dev image
make run-dev # Start dev (port 8001, Xdebug ready)
make logs-dev # View logs
make shell-dev # Access container
curl http://localhost:8001/healthTesting Workflow:
make build-test # Build with comprehensive health check
make run-test # Start test container
make test-health # Test health endpoint
make logs-test # View logsRelease Workflow:
make lint # Lint Dockerfile
make build-all # Build production + dev
make test # Run tests
make scan # Security scan
make bump-patch # Bump version
make release-all # Full release pipeline
make hub-check # Verify on Docker HubDocker Compose Workflow:
make compose-up-all # Start all services
make compose-ps # Check status
make compose-logs # View logs
make compose-open # Open in browser
make compose-down-all # Stop everythingComplete orchestration with databases, load balancing, and monitoring.
| Profile | Services | Purpose |
|---|---|---|
| Base | php-api-stack | Main application (always active) |
| db | mysql, redis-external | Databases with persistence |
| loadbalancer | nginx-lb | Nginx load balancer for scaling |
| monitoring | prometheus, grafana, cadvisor | Full monitoring stack |
# 1. Setup
cp .env.example .env
cp docker-compose.example.yml docker-compose.yml
# 2. Start base
make compose-up
# 3. Start with profiles
make compose-up PROFILES="db,monitoring"
# 4. Or start everything
make compose-up-all
# 5. Access services
make compose-open # Opens app, Prometheus, Grafana| Service | URL | Credentials |
|---|---|---|
| Application | http://localhost:8089 | - |
| Health Check | http://localhost:8089/health | - |
| Prometheus | http://localhost:9091 | - |
| Grafana | http://localhost:3000 | admin / HmlGrafana_7uV4mRp |
| MySQL | localhost:3307 | root / HmlMysql_9tQ2wRx |
# View status
make compose-ps
# View logs
make compose-logs
# Restart services
make compose-restart
# Scale application
docker compose up -d --scale php-api-stack=3
# Stop everything
make compose-down-allπ Complete guide: DOCKER_COMPOSE_GUIDE.md
# 1. Clone and setup
git clone https://github.com/kariricode/php-api-stack.git
cd php-api-stack
cp .env.example .env
# 2. Build
make build-all
# 3. Test
make test
make scan
# 4. Run dev
make run-dev
curl http://localhost:8001/health
# 5. Release
make bump-patch
make release-productionComplete guide: TESTING.md
# Quick release
make release-production
# Or step by step
make lint
make build
make test
make scan
make bump-patch
make push-productionComplete guide: DOCKER_HUB.md
# Pull and run
docker pull kariricode/php-api-stack:latest
docker run -d -p 8080:80 \
-v $(pwd)/app:/var/www/html \
kariricode/php-api-stack:latestComplete guide: IMAGE_USAGE_GUIDE.md
Two health check implementations for different needs:
Lightweight endpoint for load balancers and orchestrators:
curl http://localhost:8080/healthResponse:
{
"status": "healthy",
"timestamp": "2025-10-24T22:00:00+00:00"
}Detailed system diagnostics with component-level checks:
curl http://localhost:8080/health.php | jqFeatures:
- β PHP Runtime: Version, memory, SAPI, configuration
- β PHP Extensions: Required and optional extensions validation
- β OPcache: Hit rate, memory usage, JIT status, cached scripts
- β Redis: Connectivity, latency, stats, memory usage, persistence
- β System Resources: Disk space, CPU load, memory usage
- β Application: Directory permissions, accessibility checks
Response Structure:
{
"status": "healthy|degraded|unhealthy",
"timestamp": "2025-10-24T22:00:00+00:00",
"overall": "β All Systems Operational",
"components": {
"php": { "status": "healthy", "details": {...} },
"opcache": { "status": "healthy", "details": {...} },
"redis": { "status": "healthy", "details": {...} },
"system": { "status": "healthy", "details": {...} },
"application": { "status": "healthy", "details": {...} }
},
"stack_info": {
"docker_image": "kariricode/php-api-stack",
"version": "1.5.0",
"php_version": "8.4.13"
}
}With Docker:
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost/health || exit 1With Docker Compose:
services:
app:
image: kariricode/php-api-stack:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 3s
retries: 3With Kubernetes:
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5
periodSeconds: 30
readinessProbe:
httpGet:
path: /health.php
port: 80
initialDelaySeconds: 10
periodSeconds: 10Makefile Commands:
make test-health # Test comprehensive health check
make test-health-status # Show health summary
make test-health-watch # Live monitoring (updates every 5s)Architecture: Built with SOLID principles using Strategy, Template Method, and Facade patterns.
Production-hardened security configuration:
- β Security Headers: X-Frame-Options, X-Content-Type-Options, CSP, HSTS
- β
Rate Limiting:
- General: 10 req/s per IP
- API endpoints: 100 req/s per IP
- β Hidden Tokens: Server version and tokens hidden
- β Request Filtering: Protection against common attacks
- β
Disabled Functions:
exec,shell_exec,system,passthru, etc. - β
Open Basedir: Restricted to
/var/www/htmland/tmp - β Expose PHP: Off (version hidden)
- β File Uploads: Configurable with size limits
- β Session Security: Secure cookies, HTTP-only
- β Authentication: Password-protected (configurable)
- β Bind Address: Internal only (127.0.0.1 or network)
- β Command Renaming: Dangerous commands can be disabled
- β Persistence: AOF with fsync control
- β
Non-root User: Application runs as
www-data - β Read-only Filesystem: Where possible
- β Resource Limits: CPU and memory constraints
- β Security Scanning: Automated Trivy scans
Scan for vulnerabilities:
make scan # Scan production image
make scan-dev # Scan dev image# Check logs
docker logs <container-id>
# Test structure
make test-structure
# Check entrypoint
docker run --rm kariricode/php-api-stack:latest cat /entrypoint.sh# Check PHP-FPM socket
docker exec <container> ls -la /var/run/php/php-fpm.sock
# Check PHP-FPM status
docker exec <container> php-fpm -t
# Check logs
make logsStandalone Mode:
# Should use 127.0.0.1
docker exec <container> env | grep REDIS_HOST
# REDIS_HOST=127.0.0.1
# Test connection
docker exec <container> redis-cli -h 127.0.0.1 -a "$REDIS_PASSWORD" pingDocker Compose Mode:
# Should use 'redis' (service name)
docker compose exec php-api-stack env | grep REDIS_HOST
# REDIS_HOST=redis
# Test connection
docker compose exec php-api-stack redis-cli -h redis -a "$REDIS_PASSWORD" ping# Check container resources
docker stats <container>
# Check OPcache status
docker exec <container> php -r "print_r(opcache_get_status());"
# Check PHP-FPM pool
docker exec <container> cat /var/run/php/php-fpm.pid
docker exec <container> kill -USR2 $(cat /var/run/php/php-fpm.pid)# Check ownership
docker exec <container> ls -la /var/www/html
# Fix permissions
docker exec <container> chown -R www-data:www-data /var/www/htmlFull troubleshooting guide: IMAGE_USAGE_GUIDE.md
- PHP 8.4 Documentation
- Nginx Documentation
- Redis Documentation
- Docker Best Practices
- Symfony Best Practices
- Laravel Deployment
- Twelve-Factor App
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes
- Run tests:
make test - Lint:
make lint - Commit:
git commit -m 'feat: add amazing feature' - Push:
git push origin feature/amazing-feature - Open a Pull Request
- Code Style: Follow PSR-12 for PHP code
- Commit Messages: Use Conventional Commits
feat:New featuresfix:Bug fixesdocs:Documentation changesrefactor:Code refactoringtest:Test additions/changeschore:Build/tooling changes
- Testing: Add tests for new features
- Documentation: Update relevant documentation
make lint # Lint Dockerfile
make build-all # Build all images
make test # Run tests
make scan # Security scanThis project is licensed under the MIT License. See the LICENSE file for details.
TL;DR: You can use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the software.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Docker Hub: kariricode/php-api-stack
Found a bug? Please open an issue with:
- Docker image version
- Steps to reproduce
- Expected vs actual behavior
- Relevant logs
Have an idea? Open a discussion or issue with:
- Use case description
- Proposed solution
- Any alternative solutions considered
- β Comprehensive Makefile system with 50+ commands
- β Docker Hub automation and versioning
- β Docker Compose orchestration with profiles
- β Advanced health check system
- π Performance benchmarking suite
- π Automated CI/CD workflows
- π Multi-stage build optimization
- π Additional PECL extensions (gRPC, protobuf)
- π ARM64 native builds
- π Kubernetes manifests and Helm charts
- π Additional monitoring integrations (Datadog, New Relic)
- π Development containers (devcontainer.json)
- π PHP 8.5 support
- π Alternative web servers (Caddy, FrankenPHP)
- π WebAssembly integration
- π Enhanced security profiles
This image is part of the KaririCode ecosystem:
Modern PHP framework with advanced features:
- Repository: KaririCode-Framework
- Features: ARFA architecture, DI container, Router, Auth, etc.
- Components: 30+ independent packages
- Documentation: Comprehensive guides and examples
Development environment automation:
- Repository: kariricode/devkit
- Features: Docker + Compose, quality tools, CI/CD
- Setup Time: 2-3 minutes
- Integration: Uses this Docker image
Docker Hub Integration:
- β¨ Fixed
hub-checkcommand display bug (showing 'ag' instead of tag names) - β¨ Simplified dev tagging strategy: only
devtag (removeddev-X.Y.Z) - β¨ Fixed
bump-patch/bump-minor/bump-majordollar sign escaping - β¨ Improved
hub-checkoutput with checkmark indicators (β/β) - β¨ Added comprehensive Docker Hub utilities (
hub-tags,hub-info,hub-clean)
Breaking Changes:
β οΈ Dev versioned tags (dev-X.Y.Z) are no longer created or pushed to Docker Hub
Build System:
- β¨ Fixed PHP extension quoting in Makefile (
PHP_CORE_EXTENSIONS,PHP_PECL_EXTENSIONS) - β¨ Secure
.envparsing inbuild-from-env.shto prevent command execution - β¨ Proper escaping for build args with spaces
Redis Integration:
- β¨ Automatic
REDIS_HOSToverride to127.0.0.1for standalone containers - β¨ Smart DNS fallback in health.php for docker-compose vs standalone modes
- β¨ Documentation improvements for
REDIS_HOSTbehavior
Dockerfile Fixes:
- π Fixed OPcache validation check (Zend extension vs regular extension)
- π Added
util-linuxruntime dependency for UUID extension - π Fixed SC1075 shellcheck error (
else ifβelif) - β¨ Improved extension loading verification
Makefile Refactoring:
- β¨ Semantic grouping by similarity (Build, Push, Runtime, Test, Validation, Release)
- β¨ Enhanced development workflow with dedicated dev targets
- β¨ Improved test targets with health monitoring
- β¨ Better organization of 50+ Make targets
- π Updated documentation
- β¨ Added comprehensive Makefile with Docker Compose integration
- β¨ Added Docker Compose example with multiple profiles
- β¨ Improved documentation structure
- β¨ Enhanced health check system
- β¨ PHP 8.4, Nginx 1.27.3, Redis 7.2
- β¨ Socket-based PHP-FPM communication
- β¨ OPcache + JIT optimization
- β¨
/health.phpcomprehensive endpoint - β¨ Improved entrypoint and config processor
- β¨ Extensive environment variable configuration
- π Initial release
- β¨ PHP 8.3, Nginx 1.25, Redis 7.0
- β¨ Basic production configuration
- β¨ Docker and Docker Compose support
Made with π by KaririCode