docker.recipes

Laravel Production Stack

advanced

Production Laravel with Octane, Horizon, MySQL, and Redis.

Overview

Laravel is a modern PHP web framework that revolutionized web development with its elegant syntax and rich ecosystem. Built around the MVC pattern, Laravel provides powerful features like Eloquent ORM, Blade templating, and robust routing out of the box. Originally created by Taylor Otwell in 2011, Laravel has become the most popular PHP framework, powering millions of applications worldwide from startups to enterprise systems. This production stack combines Laravel with Octane for dramatically improved performance, Horizon for queue management and monitoring, MySQL as the primary database, Redis for caching and sessions, and NGINX for high-performance web serving. Octane uses Swoole to keep Laravel applications in memory between requests, eliminating the traditional PHP bootstrap overhead and delivering response times that rival Node.js applications. Horizon provides a beautiful dashboard and code-driven configuration for Redis queues, while the entire stack is orchestrated for maximum throughput and reliability. This configuration targets production environments where performance and scalability are critical. Enterprises running high-traffic Laravel applications, SaaS platforms with demanding performance requirements, and API-heavy applications will benefit most from this setup. The combination of Octane's memory-resident application server, Redis-backed caching and queuing, and NGINX's efficient request handling creates a Laravel deployment capable of handling thousands of concurrent requests while maintaining sub-100ms response times.

Key Features

  • Laravel Octane with Swoole server for persistent application instances and sub-50ms response times
  • Laravel Horizon dashboard for Redis queue monitoring, failed job management, and throughput metrics
  • MySQL 8.0 with InnoDB storage engine providing ACID compliance and JSON column support
  • Redis 7 Alpine for ultra-fast session storage, application caching, and queue backend
  • NGINX Alpine reverse proxy with SSL termination and static asset serving
  • Automated Laravel scheduler container running artisan commands every minute
  • Production-optimized environment variables for database connections and cache drivers
  • Isolated service networking with proper dependency management and health checks

Common Use Cases

  • 1High-traffic Laravel SaaS applications requiring sub-100ms API response times
  • 2E-commerce platforms with heavy database operations and real-time inventory updates
  • 3Content management systems serving thousands of concurrent users
  • 4API backends for mobile applications with strict performance requirements
  • 5Multi-tenant Laravel applications with complex queue processing workflows
  • 6Enterprise web applications requiring 99.9% uptime and horizontal scalability
  • 7Laravel applications with heavy background job processing and scheduled tasks

Prerequisites

  • Minimum 4GB RAM (2GB for MySQL, 1GB for Redis, 1GB for Laravel containers)
  • Docker Engine 20.10+ and Docker Compose v2 for multi-container orchestration
  • Generated Laravel APP_KEY and secure MySQL passwords in .env file
  • SSL certificates for NGINX HTTPS configuration (Let's Encrypt recommended)
  • Understanding of Laravel Octane limitations and stateful application considerations
  • Experience with Laravel queue workers and Horizon configuration

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 mysql:
3 image: mysql:8.0
4 environment:
5 - MYSQL_DATABASE=laravel
6 - MYSQL_USER=laravel
7 - MYSQL_PASSWORD=${MYSQL_PASSWORD}
8 - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
9 volumes:
10 - mysql_data:/var/lib/mysql
11 networks:
12 - laravel_net
13
14 redis:
15 image: redis:7-alpine
16 volumes:
17 - redis_data:/data
18 networks:
19 - laravel_net
20
21 laravel:
22 build:
23 context: .
24 dockerfile: Dockerfile
25 command: php artisan octane:start --server=swoole --host=0.0.0.0 --port=8000
26 environment:
27 - APP_ENV=production
28 - APP_KEY=${APP_KEY}
29 - DB_CONNECTION=mysql
30 - DB_HOST=mysql
31 - DB_DATABASE=laravel
32 - DB_USERNAME=laravel
33 - DB_PASSWORD=${MYSQL_PASSWORD}
34 - REDIS_HOST=redis
35 - CACHE_DRIVER=redis
36 - QUEUE_CONNECTION=redis
37 - SESSION_DRIVER=redis
38 volumes:
39 - laravel_storage:/app/storage
40 depends_on:
41 - mysql
42 - redis
43 networks:
44 - laravel_net
45
46 horizon:
47 build:
48 context: .
49 dockerfile: Dockerfile
50 command: php artisan horizon
51 environment:
52 - APP_ENV=production
53 - APP_KEY=${APP_KEY}
54 - DB_CONNECTION=mysql
55 - DB_HOST=mysql
56 - DB_DATABASE=laravel
57 - DB_USERNAME=laravel
58 - DB_PASSWORD=${MYSQL_PASSWORD}
59 - REDIS_HOST=redis
60 depends_on:
61 - mysql
62 - redis
63 networks:
64 - laravel_net
65
66 scheduler:
67 build:
68 context: .
69 dockerfile: Dockerfile
70 command: sh -c "while true; do php artisan schedule:run; sleep 60; done"
71 environment:
72 - APP_ENV=production
73 - APP_KEY=${APP_KEY}
74 - DB_CONNECTION=mysql
75 - DB_HOST=mysql
76 - DB_DATABASE=laravel
77 - DB_USERNAME=laravel
78 - DB_PASSWORD=${MYSQL_PASSWORD}
79 - REDIS_HOST=redis
80 depends_on:
81 - mysql
82 - redis
83 networks:
84 - laravel_net
85
86 nginx:
87 image: nginx:alpine
88 ports:
89 - "80:80"
90 - "443:443"
91 volumes:
92 - ./nginx.conf:/etc/nginx/nginx.conf:ro
93 depends_on:
94 - laravel
95 networks:
96 - laravel_net
97
98volumes:
99 mysql_data:
100 redis_data:
101 laravel_storage:
102
103networks:
104 laravel_net:

.env Template

.env
1# Laravel Production
2MYSQL_PASSWORD=secure_mysql_password
3MYSQL_ROOT_PASSWORD=secure_root_password
4APP_KEY=base64:your_app_key_here
5
6# Laravel at http://localhost
7# Horizon dashboard at /horizon

Usage Notes

  1. 1Laravel at http://localhost
  2. 2Horizon dashboard at /horizon
  3. 3Octane with Swoole for performance
  4. 4Run migrations before start
  5. 5Configure APP_KEY properly

Individual Services(6 services)

Copy individual services to mix and match with your existing compose files.

mysql
mysql:
  image: mysql:8.0
  environment:
    - MYSQL_DATABASE=laravel
    - MYSQL_USER=laravel
    - MYSQL_PASSWORD=${MYSQL_PASSWORD}
    - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
  volumes:
    - mysql_data:/var/lib/mysql
  networks:
    - laravel_net
redis
redis:
  image: redis:7-alpine
  volumes:
    - redis_data:/data
  networks:
    - laravel_net
laravel
laravel:
  build:
    context: .
    dockerfile: Dockerfile
  command: php artisan octane:start --server=swoole --host=0.0.0.0 --port=8000
  environment:
    - APP_ENV=production
    - APP_KEY=${APP_KEY}
    - DB_CONNECTION=mysql
    - DB_HOST=mysql
    - DB_DATABASE=laravel
    - DB_USERNAME=laravel
    - DB_PASSWORD=${MYSQL_PASSWORD}
    - REDIS_HOST=redis
    - CACHE_DRIVER=redis
    - QUEUE_CONNECTION=redis
    - SESSION_DRIVER=redis
  volumes:
    - laravel_storage:/app/storage
  depends_on:
    - mysql
    - redis
  networks:
    - laravel_net
horizon
horizon:
  build:
    context: .
    dockerfile: Dockerfile
  command: php artisan horizon
  environment:
    - APP_ENV=production
    - APP_KEY=${APP_KEY}
    - DB_CONNECTION=mysql
    - DB_HOST=mysql
    - DB_DATABASE=laravel
    - DB_USERNAME=laravel
    - DB_PASSWORD=${MYSQL_PASSWORD}
    - REDIS_HOST=redis
  depends_on:
    - mysql
    - redis
  networks:
    - laravel_net
scheduler
scheduler:
  build:
    context: .
    dockerfile: Dockerfile
  command: sh -c "while true; do php artisan schedule:run; sleep 60; done"
  environment:
    - APP_ENV=production
    - APP_KEY=${APP_KEY}
    - DB_CONNECTION=mysql
    - DB_HOST=mysql
    - DB_DATABASE=laravel
    - DB_USERNAME=laravel
    - DB_PASSWORD=${MYSQL_PASSWORD}
    - REDIS_HOST=redis
  depends_on:
    - mysql
    - redis
  networks:
    - laravel_net
nginx
nginx:
  image: nginx:alpine
  ports:
    - "80:80"
    - "443:443"
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf:ro
  depends_on:
    - laravel
  networks:
    - laravel_net

Quick Start

terminal
1# 1. Create the compose file
2cat > docker-compose.yml << 'EOF'
3services:
4 mysql:
5 image: mysql:8.0
6 environment:
7 - MYSQL_DATABASE=laravel
8 - MYSQL_USER=laravel
9 - MYSQL_PASSWORD=${MYSQL_PASSWORD}
10 - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
11 volumes:
12 - mysql_data:/var/lib/mysql
13 networks:
14 - laravel_net
15
16 redis:
17 image: redis:7-alpine
18 volumes:
19 - redis_data:/data
20 networks:
21 - laravel_net
22
23 laravel:
24 build:
25 context: .
26 dockerfile: Dockerfile
27 command: php artisan octane:start --server=swoole --host=0.0.0.0 --port=8000
28 environment:
29 - APP_ENV=production
30 - APP_KEY=${APP_KEY}
31 - DB_CONNECTION=mysql
32 - DB_HOST=mysql
33 - DB_DATABASE=laravel
34 - DB_USERNAME=laravel
35 - DB_PASSWORD=${MYSQL_PASSWORD}
36 - REDIS_HOST=redis
37 - CACHE_DRIVER=redis
38 - QUEUE_CONNECTION=redis
39 - SESSION_DRIVER=redis
40 volumes:
41 - laravel_storage:/app/storage
42 depends_on:
43 - mysql
44 - redis
45 networks:
46 - laravel_net
47
48 horizon:
49 build:
50 context: .
51 dockerfile: Dockerfile
52 command: php artisan horizon
53 environment:
54 - APP_ENV=production
55 - APP_KEY=${APP_KEY}
56 - DB_CONNECTION=mysql
57 - DB_HOST=mysql
58 - DB_DATABASE=laravel
59 - DB_USERNAME=laravel
60 - DB_PASSWORD=${MYSQL_PASSWORD}
61 - REDIS_HOST=redis
62 depends_on:
63 - mysql
64 - redis
65 networks:
66 - laravel_net
67
68 scheduler:
69 build:
70 context: .
71 dockerfile: Dockerfile
72 command: sh -c "while true; do php artisan schedule:run; sleep 60; done"
73 environment:
74 - APP_ENV=production
75 - APP_KEY=${APP_KEY}
76 - DB_CONNECTION=mysql
77 - DB_HOST=mysql
78 - DB_DATABASE=laravel
79 - DB_USERNAME=laravel
80 - DB_PASSWORD=${MYSQL_PASSWORD}
81 - REDIS_HOST=redis
82 depends_on:
83 - mysql
84 - redis
85 networks:
86 - laravel_net
87
88 nginx:
89 image: nginx:alpine
90 ports:
91 - "80:80"
92 - "443:443"
93 volumes:
94 - ./nginx.conf:/etc/nginx/nginx.conf:ro
95 depends_on:
96 - laravel
97 networks:
98 - laravel_net
99
100volumes:
101 mysql_data:
102 redis_data:
103 laravel_storage:
104
105networks:
106 laravel_net:
107EOF
108
109# 2. Create the .env file
110cat > .env << 'EOF'
111# Laravel Production
112MYSQL_PASSWORD=secure_mysql_password
113MYSQL_ROOT_PASSWORD=secure_root_password
114APP_KEY=base64:your_app_key_here
115
116# Laravel at http://localhost
117# Horizon dashboard at /horizon
118EOF
119
120# 3. Start the services
121docker compose up -d
122
123# 4. View logs
124docker 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/laravel-production/run | bash

Troubleshooting

  • Octane memory leaks with static variables: Restart Octane workers periodically using OCTANE_WATCH=true
  • Horizon workers not processing jobs: Check Redis connection and run 'php artisan horizon:terminate' to restart
  • MySQL connection refused errors: Verify MYSQL_PASSWORD environment variable matches across all Laravel services
  • NGINX 502 Bad Gateway: Ensure Laravel Octane is binding to 0.0.0.0:8000, not localhost
  • Laravel sessions not persisting: Confirm SESSION_DRIVER=redis and REDIS_HOST=redis in environment
  • Scheduler not executing: Check that cron jobs are running every minute and APP_KEY is properly set

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