LEMP Stack (Linux, Nginx, MySQL, PHP)
Classic LEMP stack for PHP applications.
Overview
NGINX is a high-performance HTTP server and reverse proxy that revolutionized web serving with its event-driven, asynchronous architecture. Originally developed by Igor Sysoev to solve the C10K problem, NGINX excels at handling thousands of concurrent connections with minimal resource consumption, making it the preferred choice for high-traffic websites and modern web applications.
This LEMP stack combines NGINX's superior performance characteristics with PHP-FPM's process management capabilities, MySQL's proven reliability for data storage, and phpMyAdmin's intuitive web-based administration interface. The stack leverages FastCGI Process Manager (PHP-FPM) to handle PHP requests efficiently, while NGINX serves static content directly and proxies dynamic requests to the PHP processor. MySQL 8.0 provides robust data persistence with InnoDB's ACID compliance and advanced features like JSON data types and full-text search.
Web developers, freelancers, and hosting providers will find this configuration particularly valuable for WordPress sites, custom PHP applications, and multi-tenant hosting environments. The combination delivers exceptional performance for read-heavy workloads while maintaining the simplicity that made LAMP stacks popular, but with NGINX's superior handling of concurrent connections and static file serving capabilities.
Key Features
- Event-driven NGINX architecture handling thousands of concurrent connections with minimal memory footprint
- PHP-FPM process management with optimized worker pools and graceful process recycling
- MySQL 8.0 InnoDB storage engine with ACID compliance and crash recovery
- FastCGI protocol integration between NGINX and PHP-FPM for efficient request processing
- phpMyAdmin web interface with SQL editor, import/export tools, and database visualization
- NGINX reverse proxy capabilities with built-in load balancing and health checks
- MySQL JSON data type support with native indexing and query optimization
- PHP OPcache integration for bytecode caching and improved script execution performance
Common Use Cases
- 1WordPress hosting environments requiring high concurrent user support
- 2Custom PHP web applications with complex database interactions
- 3E-commerce platforms built on PHP frameworks like Laravel or CodeIgniter
- 4Content management systems needing reliable database administration tools
- 5Development environments for PHP applications with MySQL backends
- 6Small to medium business websites requiring robust database-driven functionality
- 7Multi-tenant hosting platforms serving multiple PHP applications
Prerequisites
- Minimum 1.5GB RAM (256MB for MySQL, 256MB for NGINX, 512MB for PHP-FPM, 256MB for phpMyAdmin, plus OS overhead)
- Docker Engine 20.10+ and Docker Compose V2 for proper service orchestration
- Available ports 80, 443 (NGINX) and 8080 (phpMyAdmin) on the host system
- Basic understanding of PHP application deployment and MySQL database concepts
- Familiarity with NGINX configuration syntax for customizing virtual hosts and proxy settings
For development & testing. Review security settings, change default credentials, and test thoroughly before production use. See Terms
docker-compose.yml
docker-compose.yml
1services: 2 nginx: 3 image: nginx:alpine4 container_name: lemp-nginx5 restart: unless-stopped6 ports: 7 - "${NGINX_PORT:-80}:80"8 - "${NGINX_SSL_PORT:-443}:443"9 volumes: 10 - ./nginx.conf:/etc/nginx/nginx.conf:ro11 - ${APP_PATH:-./app}:/var/www/html12 depends_on: 13 - php1415 php: 16 image: php:8.2-fpm-alpine17 container_name: lemp-php18 restart: unless-stopped19 volumes: 20 - ${APP_PATH:-./app}:/var/www/html2122 mysql: 23 image: mysql:8.024 container_name: lemp-mysql25 restart: unless-stopped26 environment: 27 - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}28 - MYSQL_DATABASE=${DB_NAME}29 - MYSQL_USER=${DB_USER}30 - MYSQL_PASSWORD=${DB_PASSWORD}31 volumes: 32 - mysql_data:/var/lib/mysql3334 phpmyadmin: 35 image: phpmyadmin:latest36 container_name: lemp-pma37 restart: unless-stopped38 ports: 39 - "${PMA_PORT:-8080}:80"40 environment: 41 - PMA_HOST=mysql42 depends_on: 43 - mysql4445volumes: 46 mysql_data: .env Template
.env
1# LEMP Stack2NGINX_PORT=803NGINX_SSL_PORT=4434APP_PATH=./app5DB_ROOT_PASSWORD=root_password6DB_NAME=app7DB_USER=app8DB_PASSWORD=app_password9PMA_PORT=8080Usage Notes
- 1App at http://localhost
- 2phpMyAdmin at http://localhost:8080
- 3Place PHP files in ./app
- 4Configure nginx for your app
Individual Services(4 services)
Copy individual services to mix and match with your existing compose files.
nginx
nginx:
image: nginx:alpine
container_name: lemp-nginx
restart: unless-stopped
ports:
- ${NGINX_PORT:-80}:80
- ${NGINX_SSL_PORT:-443}:443
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ${APP_PATH:-./app}:/var/www/html
depends_on:
- php
php
php:
image: php:8.2-fpm-alpine
container_name: lemp-php
restart: unless-stopped
volumes:
- ${APP_PATH:-./app}:/var/www/html
mysql
mysql:
image: mysql:8.0
container_name: lemp-mysql
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MYSQL_DATABASE=${DB_NAME}
- MYSQL_USER=${DB_USER}
- MYSQL_PASSWORD=${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
phpmyadmin
phpmyadmin:
image: phpmyadmin:latest
container_name: lemp-pma
restart: unless-stopped
ports:
- ${PMA_PORT:-8080}:80
environment:
- PMA_HOST=mysql
depends_on:
- mysql
Quick Start
terminal
1# 1. Create the compose file2cat > docker-compose.yml << 'EOF'3services:4 nginx:5 image: nginx:alpine6 container_name: lemp-nginx7 restart: unless-stopped8 ports:9 - "${NGINX_PORT:-80}:80"10 - "${NGINX_SSL_PORT:-443}:443"11 volumes:12 - ./nginx.conf:/etc/nginx/nginx.conf:ro13 - ${APP_PATH:-./app}:/var/www/html14 depends_on:15 - php1617 php:18 image: php:8.2-fpm-alpine19 container_name: lemp-php20 restart: unless-stopped21 volumes:22 - ${APP_PATH:-./app}:/var/www/html2324 mysql:25 image: mysql:8.026 container_name: lemp-mysql27 restart: unless-stopped28 environment:29 - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}30 - MYSQL_DATABASE=${DB_NAME}31 - MYSQL_USER=${DB_USER}32 - MYSQL_PASSWORD=${DB_PASSWORD}33 volumes:34 - mysql_data:/var/lib/mysql3536 phpmyadmin:37 image: phpmyadmin:latest38 container_name: lemp-pma39 restart: unless-stopped40 ports:41 - "${PMA_PORT:-8080}:80"42 environment:43 - PMA_HOST=mysql44 depends_on:45 - mysql4647volumes:48 mysql_data:49EOF5051# 2. Create the .env file52cat > .env << 'EOF'53# LEMP Stack54NGINX_PORT=8055NGINX_SSL_PORT=44356APP_PATH=./app57DB_ROOT_PASSWORD=root_password58DB_NAME=app59DB_USER=app60DB_PASSWORD=app_password61PMA_PORT=808062EOF6364# 3. Start the services65docker compose up -d6667# 4. View logs68docker compose logs -fOne-Liner
Run this command to download and set up the recipe in one step:
terminal
1curl -fsSL https://docker.recipes/api/recipes/nginx-php-mysql-stack/run | bashTroubleshooting
- 502 Bad Gateway errors: Check PHP-FPM container status and ensure FastCGI configuration in NGINX points to correct PHP service name
- MySQL connection refused: Verify MySQL container is fully initialized before PHP attempts connections, add healthcheck or depends_on conditions
- phpMyAdmin 'Cannot connect: invalid settings' error: Confirm PMA_HOST environment variable matches MySQL service name in docker-compose
- PHP files downloading instead of executing: Verify NGINX configuration includes proper location blocks for .php files and FastCGI parameters
- Permission denied errors on app files: Ensure proper file ownership and permissions in mounted volume, PHP-FPM runs as www-data user
- MySQL 'Authentication plugin caching_sha2_password' errors: Use MySQL 8.0 compatible connection methods or configure mysql_native_password for legacy PHP applications
Community Notes
Loading...
Loading notes...
Download Recipe Kit
Get all files in a ready-to-deploy package
Includes docker-compose.yml, .env template, README, and license
Ad Space
Shortcuts: C CopyF FavoriteD Download