laravel生产部署需六步:一、安装php 8.1+、nginx、mysql、composer及必要扩展;二、git克隆代码并运行composer install --no-dev --optimize-autoloader;三、设app_env=production、app_debug=false,生成密钥,禁止.env网络访问;四、nginx root指向public,配置try_files与php处理;五、chown -r www-data:www-data storage bootstrap/cache;六、执行migrate --force及config:cache、route:cache、view:cache。

将Laravel应用部署到生产环境时,必须确保PHP版本、扩展、数据库连接、缓存配置和HTTPS支持全部符合线上要求,任何一项配置偏差都可能导致500错误或连接超时。
准备生产级项目结构
在项目根目录创建docker子目录,统一存放所有容器化配置,避免污染Laravel源码目录。
执行命令:mkdir -p docker/production/{php-fpm,nginx} docker/common/php-fpm。
把.env.example复制为.env.production,并填入真实数据库密码、APP_KEY、REDIS_PASSWORD等敏感值——【.env.production不可提交到Git】。
创建compose.prod.yaml,不复用开发用的docker-compose.yml,防止误启开发服务暴露调试接口。
构建精简安全的PHP-FPM镜像
方法一:多阶段构建(推荐)
在docker/production/php-fpm/Dockerfile中写入:
FROM php:8.4-fpm-alpine AS builder→安装扩展→RUN docker-php-ext-install pdo_mysql opcache pcntl→COPY . /var/www/html→RUN composer install --no-dev --optimize-autoloader;第二阶段FROM php:8.4-fpm-alpine→COPY --from=builder /var/www/html /var/www/html→RUN chown -R www-data:www-data /var/www/html。
方法二:基础镜像直接构建
若跳过多阶段,直接使用php:8.4-fpm-alpine,但必须删除dev类扩展(如xdebug、opcache GUI),否则会拖慢响应并暴露调试入口。
⚠️注意:不要在生产镜像中保留composer二进制文件,它不属于运行时依赖,仅在构建阶段需要。
配置Nginx反向代理与HTTPS强制跳转
第一步:在docker/production/nginx/nginx.conf中定义server块,监听80端口并301重定向到HTTPS。
第二步:添加SSL证书挂载配置,从宿主机映射/etc/nginx/ssl/fullchain.pem和/etc/nginx/ssl/privkey.pem。
第三步:启用Laravel标准重写规则,确保try_files $uri $uri/ /index.php?$query_string生效——【缺少这行会导致所有路由返回404】。
第四步:关闭Nginx版本号输出,添加server_tokens off;防止暴露软件版本信息。
编排生产服务并设置健康检查
在compose.prod.yaml中定义postgres服务时,必须配置volumes绑定持久化路径,并加入健康检查语句:
healthcheck:→test: ["CMD", "pg_isready", "-U", "laravel", "-d", "laravel"]→interval: 30s→timeout: 10s→retries: 5。
web服务需声明depends_on:→postgres:→condition: service_healthy,确保数据库就绪后再启动PHP-FPM。
为redis服务添加restart: unless-stopped,避免因短暂网络抖动导致队列服务中断。
启动并验证生产容器
执行docker-compose -f compose.prod.yaml --env-file .env.production up -d。
等待30秒后,运行docker-compose -f compose.prod.yaml logs -f web查看PHP-FPM是否正常加载index.php。
用curl -I http://localhost确认返回状态码为301,再用curl -kI https://localhost确认返回200且X-Powered-By头已被移除。
进入web容器执行php artisan tinker,输入config('database.connections.mysql.host'),输出必须是postgres而非localhost。











