docker.recipes

LEMP Stack (Linux, Nginx, MySQL, PHP)

intermediate

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:alpine
4 container_name: lemp-nginx
5 restart: unless-stopped
6 ports:
7 - "${NGINX_PORT:-80}:80"
8 - "${NGINX_SSL_PORT:-443}:443"
9 volumes:
10 - ./nginx.conf:/etc/nginx/nginx.conf:ro
11 - ${APP_PATH:-./app}:/var/www/html
12 depends_on:
13 - php
14
15 php:
16 image: php:8.2-fpm-alpine
17 container_name: lemp-php
18 restart: unless-stopped
19 volumes:
20 - ${APP_PATH:-./app}:/var/www/html
21
22 mysql:
23 image: mysql:8.0
24 container_name: lemp-mysql
25 restart: unless-stopped
26 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/mysql
33
34 phpmyadmin:
35 image: phpmyadmin:latest
36 container_name: lemp-pma
37 restart: unless-stopped
38 ports:
39 - "${PMA_PORT:-8080}:80"
40 environment:
41 - PMA_HOST=mysql
42 depends_on:
43 - mysql
44
45volumes:
46 mysql_data:

.env Template

.env
1# LEMP Stack
2NGINX_PORT=80
3NGINX_SSL_PORT=443
4APP_PATH=./app
5DB_ROOT_PASSWORD=root_password
6DB_NAME=app
7DB_USER=app
8DB_PASSWORD=app_password
9PMA_PORT=8080

Usage Notes

  1. 1App at http://localhost
  2. 2phpMyAdmin at http://localhost:8080
  3. 3Place PHP files in ./app
  4. 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 file
2cat > docker-compose.yml << 'EOF'
3services:
4 nginx:
5 image: nginx:alpine
6 container_name: lemp-nginx
7 restart: unless-stopped
8 ports:
9 - "${NGINX_PORT:-80}:80"
10 - "${NGINX_SSL_PORT:-443}:443"
11 volumes:
12 - ./nginx.conf:/etc/nginx/nginx.conf:ro
13 - ${APP_PATH:-./app}:/var/www/html
14 depends_on:
15 - php
16
17 php:
18 image: php:8.2-fpm-alpine
19 container_name: lemp-php
20 restart: unless-stopped
21 volumes:
22 - ${APP_PATH:-./app}:/var/www/html
23
24 mysql:
25 image: mysql:8.0
26 container_name: lemp-mysql
27 restart: unless-stopped
28 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/mysql
35
36 phpmyadmin:
37 image: phpmyadmin:latest
38 container_name: lemp-pma
39 restart: unless-stopped
40 ports:
41 - "${PMA_PORT:-8080}:80"
42 environment:
43 - PMA_HOST=mysql
44 depends_on:
45 - mysql
46
47volumes:
48 mysql_data:
49EOF
50
51# 2. Create the .env file
52cat > .env << 'EOF'
53# LEMP Stack
54NGINX_PORT=80
55NGINX_SSL_PORT=443
56APP_PATH=./app
57DB_ROOT_PASSWORD=root_password
58DB_NAME=app
59DB_USER=app
60DB_PASSWORD=app_password
61PMA_PORT=8080
62EOF
63
64# 3. Start the services
65docker compose up -d
66
67# 4. View logs
68docker compose logs -f

One-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 | bash

Troubleshooting

  • 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