Laravel 应用 Docker 容器化指南

把 Laravel 应用装进 Docker 的完整流程:编写 Dockerfile、构建镜像、Docker Compose 编排 PHP-FPM/Nginx/MySQL 服务。开发与生产两种语境的配置要点一次讲清。

最佳实践
容器模块与编排港口插画

本文依据官方文档整理,未执行运行验证或性能基准。代码片段展示局部用法,业务函数、数据和环境需按项目补齐;版本与配置以所引文档为准。

直接回答:Laravel 容器化的标准形态是 Docker Compose 三件套——PHP-FPM 容器跑应用、Nginx 容器做 Web 入口、MySQL 容器存数据,开发环境可共享源码挂载,生产镜像应包含锁定的代码与 vendor。Dockerfile 基于 php:fpm 装扩展、Composer 装依赖;生产版要关闭 Xdebug、开启 OPcache、用多阶段构建瘦身。

整体架构

浏览器 → Nginx 容器 :80 → PHP-FPM 容器 :9000 → MySQL 容器 :3306

以下 Compose 是本地开发示意,不是可直接上线的完整清单。生产应把应用代码和 vendor 构建进镜像,Nginx 只需公开资源及与 FPM 一致的脚本路径。

Dockerfile 要点

FROM php:8.3-fpm
RUN apt-get update && apt-get install -y libpng-dev libzip-dev \
    && docker-php-ext-install pdo_mysql gd zip opcache
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www
COPY . .
RUN composer install --no-dev --optimize-autoloader

构建上下文须用 .dockerignore 排除 .env、.git 和本机 vendor;补齐 composer.lock 对 PHP 与扩展的要求,并给 storage/bootstrap/cache 最小写权限。关键点:扩展用官方 docker-php-ext-install 装;Composer 用多阶段复制而非镜像内安装;生产构建 --no-dev。

Compose 编排

services:
  app:
    build: .
    volumes: [".:/var/www"]
  web:
    image: nginx:alpine
    ports: ["80:80"]
    volumes: [".:/var/www", "./nginx.conf:/etc/nginx/conf.d/default.conf"]
  db:
    image: mysql:8
    environment: { MYSQL_DATABASE: blog, MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:?set a development root password}" }

还需编写 nginx.conf:root 指向 /var/www/public,PHP 请求通过 fastcgi_pass app:9000 交给 FPM,并正确设置 SCRIPT_FILENAME。示例未包含完整 Nginx 配置、应用数据库用户、健康检查和数据库持久卷,必须补全后运行;勿将 FPM 9000 端口暴露公网。

首次请求失败时,先分别查看 Nginx 和 PHP-FPM 日志:前者确认转发结果,后者查脚本路径或权限错误。使用观测云集中采集时,按 DataKit 日志采集指南为两类日志设置不同来源和一致的服务标签,保留同一请求的时间与标识。

生产语境的差异

  • 关闭 Xdebug、开 OPcache(opcache.validate_timestamps=0)
  • .env 不进镜像,运行时注入
  • 配置注入完成后执行 php artisan config:cache;迁移由受控的单独部署任务执行,先备份、审核破坏性变更,避免每个副本启动时竞相迁移
  • 多阶段构建:依赖层与代码层分离,最终镜像只留运行时

常见问题(FAQ)

Q:开发环境也用这套吗?
A:用同一套 Compose 文件,但开 Xdebug、挂源码、开 OPcache 时间戳校验(opcache.validate_timestamps=1)——用 compose override 文件区分两套配置。

Q:队列与计划任务怎么容器化?
A:各起独立容器:php artisan queue:work 与 php artisan schedule:work(或 cron 每分钟调 schedule:run),复用同一镜像不同启动命令。

Q:镜像里的 vendor 和挂载的源码冲突怎么办?
A:volume 会覆盖容器内代码目录。做法:开发环境在挂载目录预装与 lock 文件一致的 vendor,或用显式初始化的命名卷。生产不挂载覆盖代码,也不在每次启动时联网装依赖。

官方参考

资料核对日期:2026-09-29。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台