Laravel Production Deployment: Step-by-Step Guide
Laravel is the most popular PHP framework, offering elegant syntax, a powerful ORM (Eloquent), queue system, and rich ecosystem. Deploying Laravel to production requires proper Docker configuration, PHP-FPM process management, Nginx as the web server, and careful attention to the APP_ENV and caching settings.
This guide walks through a complete Laravel production deployment on [PandaStack](https://pandastack.io).
Laravel's Production Requirements
Before deploying, Laravel needs:
- PHP 8.2+ with required extensions (pdo_pgsql, mbstring, openssl, tokenizer, xml, ctype, json)
- Composer dependencies installed without dev packages
- Application key generated (
APP_KEY) - Configuration cached for performance (
php artisan config:cache) - Routes and views cached (
php artisan route:cache,php artisan view:cache)
Project Structure
myapp/
├── app/
├── config/
├── database/
│ └── migrations/
├── public/
├── routes/
├── storage/
├── docker/
│ ├── nginx/
│ │ └── default.conf
│ └── php/
│ └── php.ini
├── Dockerfile
└── pandastack.jsonNginx Configuration
# docker/nginx/default.conf
server {
listen 80;
root /var/www/public;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location /health {
access_log off;
return 200 '{"status":"ok"}';
add_header Content-Type application/json;
}
}Production Dockerfile
FROM php:8.3-fpm-alpine AS base
RUN apk add --no-cache nginx postgresql-dev libzip-dev && docker-php-ext-install pdo_pgsql zip bcmath opcache
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
FROM base AS deps
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-interaction --optimize-autoloader --no-scripts
FROM base AS runner
COPY --from=deps /var/www/vendor ./vendor
COPY . .
COPY docker/nginx/default.conf /etc/nginx/http.d/default.conf
RUN chown -R www-data:www-data storage bootstrap/cache && chmod -R 775 storage bootstrap/cache
RUN php artisan config:cache && php artisan route:cache && php artisan view:cache
EXPOSE 80
COPY docker/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]Startup Entrypoint
#!/bin/sh
# docker/entrypoint.sh
set -e
php artisan migrate --force --no-interaction
php-fpm -D
nginx -g "daemon off;"The --force flag runs migrations without prompting in production. Running PHP-FPM as a background daemon, then Nginx in the foreground, keeps the container alive.
Configuring pandastack.json
{
"type": "container",
"healthCheckPath": "/health"
}The Nginx config above returns a health response from /health without invoking PHP, making it fast and reliable for platform health checks.
Environment Variables
Laravel reads configuration from environment variables. Set these in the PandaStack dashboard at [dashboard.pandastack.io](https://dashboard.pandastack.io):
APP_NAME=MyApp
APP_ENV=production
APP_KEY=base64:your-generated-key-here
APP_DEBUG=false
APP_URL=https://yourdomain.com
DB_CONNECTION=pgsql
DB_HOST=pg.internal.pandastack.io
DB_PORT=5432
DB_DATABASE=myapp_prod
DB_USERNAME=myapp_user
DB_PASSWORD=your-secure-password
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
REDIS_URL=redis://redis.internal:6379
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_USERNAME=your-mailgun-user
MAIL_PASSWORD=your-mailgun-passwordGenerate your APP_KEY locally with:
php artisan key:generate --showCopy the output and set it as APP_KEY in the dashboard.
Provisioning a Database
PandaStack provides managed PostgreSQL, MySQL, Redis, and MongoDB instances. Provision a PostgreSQL instance from the Databases section at [dashboard.pandastack.io](https://dashboard.pandastack.io) and copy the connection details into your environment variables.
OPcache Configuration
Add OPcache configuration for PHP performance:
; docker/php/php.ini
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0
opcache.save_comments=1Setting opcache.validate_timestamps=0 in production tells PHP not to check for file changes on every request, significantly improving throughput.
GitHub Integration and Deployment
Connect your GitHub repository from the PandaStack dashboard. Every push to your production branch builds and deploys automatically. For CLI deployments:
npm install -g @pandastack/cli
panda deployProduction Checklist
APP_ENV=productionandAPP_DEBUG=falseAPP_KEYis set and secure- Config, route, and view caches are built in the Docker image
- Migrations run via
php artisan migrate --forceon startup - OPcache is enabled and tuned
- Redis is used for session, cache, and queue
healthCheckPathpoints to/healthinpandastack.json
Queue Workers with Laravel
Laravel's queue system (backed by Redis) processes background jobs asynchronously. To run queue workers in production, deploy a second container project using the same Docker image with the queue worker command. You can also configure this as a PandaStack cronjob that keeps the worker process running.
# Override the container command for queue workers
php artisan queue:work redis --sleep=3 --tries=3 --max-time=3600Failed jobs are stored in the failed_jobs table and can be retried with php artisan queue:retry all. Always configure a dead-letter queue and monitoring for production job failures.
Laravel Horizon for Queue Monitoring
For production queue visibility, Laravel Horizon provides a beautiful dashboard for monitoring Redis queue throughput, job failure rates, and worker status. Add it to your project:
composer require laravel/horizon
php artisan horizon:installRun Horizon instead of the plain queue worker for better observability:
php artisan horizonProtect the Horizon dashboard in production by restricting access in app/Providers/HorizonServiceProvider.php to specific email addresses or IP ranges — Horizon exposes queue internals and should never be publicly accessible.
Visit [docs.pandastack.io](https://docs.pandastack.io) for more deployment resources.