Production-ready multi-stage Docker stack with PHP-FPM, Nginx, Redis, Composer, and Symfony CLI
3.1K
Production-ready PHP API Stack image built on Alpine Linux with Nginx + PHP-FPM + Redis. Secured, fast, and fully configurable via environment variables โ ideal for modern APIs, web applications, and microservices.
Pull and run the demo page:
docker pull kariricode/php-api-stack:latest
docker run -d -p 8080:80 --name my-app kariricode/php-api-stack:latest
# Open: http://localhost:8080
You'll see a comprehensive status page showing PHP version, loaded extensions, OPcache statistics, Redis connectivity, and system resources.
docker run -d \
-p 8080:80 \
--name my-app \
-e APP_ENV=production \
-e PHP_MEMORY_LIMIT=512M \
-e PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \
-v $(pwd)/app:/var/www/html:ro \
kariricode/php-api-stack:latest
Important: Your application's public entry point must be at /var/www/html/public/index.php (Symfony/Laravel standard).
Create docker-compose.yml:
version: '3.9'
services:
app:
image: kariricode/php-api-stack:latest
container_name: my-app
ports:
- "8080:80"
environment:
APP_ENV: production
PHP_MEMORY_LIMIT: 512M
PHP_FPM_PM_MAX_CHILDREN: 100
REDIS_HOST: 127.0.0.1 # Using internal Redis
volumes:
- ./app:/var/www/html:ro
- ./logs:/var/log
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 3s
retries: 3
restart: unless-stopped
version: '3.9'
services:
app:
image: kariricode/php-api-stack:latest
container_name: my-app
ports:
- "8080:80"
environment:
APP_ENV: production
DATABASE_URL: mysql://user:pass@db:3306/myapp
REDIS_HOST: 127.0.0.1 # Internal Redis
volumes:
- ./app:/var/www/html:ro
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
restart: unless-stopped
networks:
- app-network
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: myapp
MYSQL_USER: user
MYSQL_PASSWORD: pass
volumes:
- db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- app-network
volumes:
db-data:
networks:
app-network:
driver: bridge
Note about Redis: This image includes an internal Redis instance on 127.0.0.1:6379. For external Redis, create a separate service and set REDIS_HOST to the service name.
Start services:
docker compose up -d
docker compose logs -f
docker compose ps
| Tag | Description | Size | Use Case |
|---|---|---|---|
latest | Latest stable release | ~225MB | General use |
1.5.0 | Specific version | ~225MB | Production (pinned) |
1.5 | Latest patch in v1.5.x | ~225MB | Auto-patch updates |
1 | Latest minor in v1.x.x | ~225MB | Auto-minor updates |
dev | Development build | ~244MB | Local development with Xdebug |
test | With comprehensive health checks | ~216MB | Testing/monitoring |
1.5.0) for reproducibilitydev tag for debugging capabilities1.5) for automatic patch updateslatest in productionPull a specific tag:
docker pull kariricode/php-api-stack:1.5.0
docker pull kariricode/php-api-stack:dev
All configuration is done via environment variables. The image supports 100+ configuration options covering PHP, PHP-FPM, Nginx, Redis, and application settings.
# Application
APP_ENV=production # production|development|test
APP_DEBUG=false # Enable debug mode
APP_NAME=my-application # Application name
# PHP Runtime
PHP_MEMORY_LIMIT=512M # Memory per request
PHP_MAX_EXECUTION_TIME=60 # Script timeout
PHP_UPLOAD_MAX_FILESIZE=100M # Max upload size
PHP_POST_MAX_SIZE=100M # Max POST size
PHP_DATE_TIMEZONE=UTC # Timezone
# PHP-FPM
PHP_FPM_PM=static # static|dynamic|ondemand
PHP_FPM_PM_MAX_CHILDREN=100 # Worker processes
# OPcache
PHP_OPCACHE_ENABLE=1 # Enable OPcache
PHP_OPCACHE_MEMORY=256 # OPcache memory (MB)
PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 # 0 for prod, 1 for dev
PHP_OPCACHE_JIT=tracing # JIT mode
# Nginx
NGINX_WORKER_PROCESSES=auto # auto = CPU cores
NGINX_CLIENT_MAX_BODY_SIZE=100M # Max request size
# Redis (Internal)
REDIS_HOST=127.0.0.1 # Internal Redis (standalone)
REDIS_PASSWORD= # Optional password
Complete reference: See .env.exampleโ in the repository.
docker run -d \
-p 80:80 \
-e PHP_MEMORY_LIMIT=512M \
-e PHP_FPM_PM=static \
-e PHP_FPM_PM_MAX_CHILDREN=200 \
-e PHP_OPCACHE_MEMORY=512 \
-e PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \
-e PHP_OPCACHE_JIT=tracing \
-e NGINX_WORKER_CONNECTIONS=4096 \
-v $(pwd)/app:/var/www/html:ro \
kariricode/php-api-stack:latest
docker run -d \
-p 80:80 \
--memory="512m" \
-e PHP_MEMORY_LIMIT=256M \
-e PHP_FPM_PM=dynamic \
-e PHP_FPM_PM_MAX_CHILDREN=25 \
-e PHP_OPCACHE_MEMORY=128 \
-v $(pwd)/app:/var/www/html:ro \
kariricode/php-api-stack:latest
| Component | Version | Purpose |
|---|---|---|
| PHP-FPM | 8.4.13 | PHP processing with optimized pool |
| Nginx | 1.27.3 | High-performance web server |
| Redis | 7.2.11 | Cache and session management |
| Alpine Linux | 3.21 | Minimal base image |
| Composer | 2.8.12 | PHP dependency manager |
| Symfony CLI | 5.15.1 | Symfony tools (dev only) |
| Xdebug | 3.4.6 | PHP debugger (dev only) |
Core Extensions (Pre-installed):
pdo, pdo_mysql, opcache, intl, zip, bcmath, gd, mbstring, xml, sockets
PECL Extensions (Pre-installed):
redis (6.1.0), apcu (5.1.24), uuid (1.2.1), imagick (3.7.0), amqp (2.1.2)
Built-in Extensions (Always available):
json, curl, fileinfo, ctype, iconv, session, tokenizer, filter, hash, openssl
Lightweight endpoint for load balancers and orchestrators:
curl http://localhost:8080/health
# Response: healthy
HTTP 200 if healthy, 503 if unhealthy.
Detailed diagnostics with component-level checks:
curl http://localhost:8080/health.php | jq
Returns JSON with:
Docker Healthcheck:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 10s
Kubernetes Probes:
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health.php
port: 80
initialDelaySeconds: 10
periodSeconds: 5
docker run -d \
-p 8080:80 \
-e APP_ENV=prod \
-e APP_SECRET=$(openssl rand -hex 16) \
-e DATABASE_URL=mysql://user:pass@db:3306/symfony \
-v $(pwd):/var/www/html:ro \
kariricode/php-api-stack:latest
docker run -d \
-p 8080:80 \
-e APP_ENV=production \
-e APP_KEY=base64:your-key-here \
-e DB_CONNECTION=mysql \
-e DB_HOST=db \
-e DB_DATABASE=laravel \
-v $(pwd):/var/www/html:ro \
kariricode/php-api-stack:latest
docker run -d \
-p 8080:80 \
-e APP_ENV=production \
-v $(pwd)/my-app:/var/www/html:ro \
kariricode/php-api-stack:latest
Directory Structure: Your app must have public/index.php as the entry point.
www-data, nginx, redis)/var/www/html and /tmp:ro)The dev tag includes additional tools for local development:
docker run -d \
-p 8001:80 \
-p 9003:9003 \
-e APP_ENV=development \
-e APP_DEBUG=true \
-e PHP_DISPLAY_ERRORS=On \
-e XDEBUG_ENABLE=1 \
-v $(pwd)/app:/var/www/html \
kariricode/php-api-stack:dev
Includes:
# Quick version check
docker run --rm kariricode/php-api-stack:latest php -v
# Full test suite
docker run --rm kariricode/php-api-stack:test /usr/local/bin/health-check.sh
The repository includes three specialized Makefiles with 50+ commands:
make build # Build production image
make build-dev # Build dev image
make run # Run production container
make run-dev # Run dev container
make test # Run test suite
make lint # Lint Dockerfile
make scan # Security scan
make hub-help # Show Docker Hub commands
make version # Show current version
make bump-patch # Bump patch version
make tag-production # Tag production image
make push-production # Push to Docker Hub
make release-production # Full release pipeline
make compose-help # Show Compose commands
make compose-up # Start services
make compose-logs # View logs
make compose-shell # Access container
Get the source: https://github.com/kariricode/php-api-stackโ
# Check logs
docker logs <container-name>
# Common causes:
# - Port already in use โ Change port: -p 8081:80
# - Volume permissions โ Fix: chmod -R 755 app/
# - Memory limits โ Increase: --memory="1g"
# Check PHP-FPM
docker exec <container> ps aux | grep php-fpm
# Check logs
docker exec <container> tail -f /var/log/php/fpm-error.log
docker exec <container> tail -f /var/log/nginx/error.log
# Restart PHP-FPM
docker exec <container> kill -USR2 $(cat /var/run/php/php-fpm.pid)
# Check Redis (internal)
docker exec <container> redis-cli -h 127.0.0.1 ping
# Should return: PONG
# Check REDIS_HOST variable
docker exec <container> env | grep REDIS_HOST
# Should be: 127.0.0.1 (standalone) or redis (compose)
# Test with password (if configured)
docker exec <container> redis-cli -h 127.0.0.1 -a "password" ping
# Check OPcache hit rate (should be >95%)
docker exec <container> php -r "
\$stats = opcache_get_status()['opcache_statistics'];
echo 'Hit Rate: ' . \$stats['opcache_hit_rate'] . '%' . PHP_EOL;
"
# Check resource usage
docker stats <container>
# Solutions:
# - Increase OPcache memory: -e PHP_OPCACHE_MEMORY=512
# - Increase FPM workers: -e PHP_FPM_PM_MAX_CHILDREN=100
# - Add container resources: --memory="2g" --cpus="4"
Complete troubleshooting guide: IMAGE_USAGE_GUIDE.mdโ
| Document | Description |
|---|---|
| README.mdโ | Project overview and quick start |
| IMAGE_USAGE_GUIDE.mdโ | Complete usage guide for end users |
| DOCKER_COMPOSE_GUIDE.mdโ | Docker Compose orchestration |
| TESTING.mdโ | Testing procedures for maintainers |
Docker Hub Integration:
hub-check command display bugdev tag (removed dev-X.Y.Z)bump-patch, bump-minor, bump-major)hub-check output with checkmarks (โ/โ)Breaking Changes:
dev-X.Y.Z) are no longer createdBuild System:
.env parsing to prevent command executionRedis Integration:
REDIS_HOST override for standalone containersDockerfile:
util-linux for UUID extensionFull changelog: GitHub Releasesโ
This image is part of the KaririCode ecosystem:
Modern PHP framework with advanced features:
Development environment automation:
Contributions are welcome! Please:
Standards:
This project is licensed under the MIT License.
See LICENSEโ in the repository.
Made with ๐ by KaririCodeโ
Content type
Image
Digest
sha256:3ea2a954cโฆ
Size
88.7 MB
Last updated
10 months ago
docker pull kariricode/php-api-stack