Docker部署Laravel项目详细教程
使用Docker部署Laravel项目是现代Web开发的流行选择,它通过容器化技术实现环境一致性,简化配置流程。本文将深入探讨如何利用Docker部署Laravel应用,包括创建Dockerfile定义PHP应用容器、配置Nginx转发请求、编写docker-compose.yml编排多服务(如app、web、db、redis),以及执行Docker命令构建和启动服务。此外,文章还将着重介绍生产环境的优化策略,如多阶段构建镜像、资源限制、日志管理、秘密管理和CI/CD集成。通过Docker,开发者可以有效解决“本地能跑”的问题,提升开发效率和部署质量。
部署Laravel项目用Docker的核心在于实现环境一致性并简化配置,具体通过以下步骤:1. 创建Dockerfile,定义PHP应用容器,基于php:8.2-fpm-alpine镜像,安装必要扩展与依赖,设置工作目录并暴露9000端口;2. 配置Nginx文件,转发请求至PHP-FPM容器,确保fastcgi_pass指向正确的服务名;3. 编写docker-compose.yml编排服务,包含app、web、db、redis等容器,设置依赖关系、数据卷、网络和环境变量;4. 执行docker-compose命令构建并启动服务,进入容器运行Laravel相关命令;5. 生产环境优化包括多阶段构建镜像、资源限制、日志策略、秘密管理、CI/CD集成、Laravel优化命令及监控警报配置。Docker解决了“本地能跑”的问题,提供环境一致性、快速上手、依赖隔离、可移植性和扩展基础。最佳实践包括服务分离、合理使用数据卷、清晰网络配置、环境变量管理及健康检查。生产环境部署需特别注意镜像优化、资源限制、日志集中管理、安全敏感信息处理,并集成自动化部署流程,确保应用稳定高效运行。
用Docker部署Laravel项目,核心在于将PHP应用、Web服务器(如Nginx)和数据库(如MySQL)各自封装在独立的容器中,并通过Docker Compose协调它们协同工作,实现开发与生产环境的一致性部署,极大简化了环境配置的复杂性。

解决方案
要用Docker部署一个Laravel PHP项目,我们通常会用到三个核心文件:Dockerfile
(定义应用容器的构建方式)、Nginx配置文件(作为Web服务器),以及docker-compose.yml
(编排所有服务)。
我通常会从创建一个Dockerfile
开始,它就像是为我的Laravel应用定制的“家”。这个文件会指定基础镜像(比如php:8.2-fpm-alpine
,我喜欢Alpine因为它小巧),安装必要的PHP扩展(pdo_mysql
, bcmath
, gd
等),并把我的应用代码复制进去。说实话,最初我总会漏掉几个扩展,导致项目跑不起来,后来才学乖了,把所有依赖都列得清清楚楚。

# Dockerfile FROM php:8.2-fpm-alpine # 安装系统依赖和PHP扩展 RUN apk add --no-cache \ nginx \ mysql-client \ git \ supervisor \ && docker-php-ext-install \ pdo_mysql \ bcmath \ gd \ exif \ pcntl \ sockets \ && docker-php-ext-enable pdo_mysql bcmath gd exif pcntl sockets # 安装Composer COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer # 设置工作目录 WORKDIR /var/www/html # 复制应用代码 COPY . . # 安装Composer依赖 RUN composer install --no-dev --optimize-autoloader --no-interaction # 配置Laravel权限 RUN chown -R www-data:www-data storage bootstrap/cache \ && chmod -R 775 storage bootstrap/cache # 暴露PHP-FPM端口 EXPOSE 9000 # 启动PHP-FPM CMD ["php-fpm"]
接着是Nginx的配置,它负责将外部请求转发给PHP-FPM容器。我通常会创建一个nginx.conf
文件,放在项目的某个地方,比如docker/nginx/default.conf
。这里面最关键的就是fastcgi_pass
指向PHP-FPM服务。
# docker/nginx/default.conf server { listen 80; server_name localhost; root /var/www/html/public; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; index index.php index.html index.htm; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass app:9000; # 'app' 是docker-compose.yml中PHP服务的名称 fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.ht { deny all; } }
最后,也是最关键的,是docker-compose.yml
文件。它就像一个指挥家,协调所有的服务(应用、Nginx、数据库、Redis等)一起工作。

# docker-compose.yml version: '3.8' services: app: build: context: . dockerfile: Dockerfile container_name: laravel_app restart: unless-stopped volumes: - .:/var/www/html - /var/www/html/vendor # 避免宿主机vendor目录权限问题,或者在Dockerfile中安装依赖 networks: - laravel_network web: image: nginx:alpine container_name: laravel_web restart: unless-stopped ports: - "80:80" volumes: - .:/var/www/html - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf depends_on: - app networks: - laravel_network db: image: mysql:8.0 container_name: laravel_db restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_DATABASE: ${DB_DATABASE} MYSQL_USER: ${DB_USERNAME} MYSQL_PASSWORD: ${DB_PASSWORD} volumes: - db_data:/var/lib/mysql networks: - laravel_network ports: - "3306:3306" # 仅在开发环境暴露,生产环境不建议 redis: image: redis:alpine container_name: laravel_redis restart: unless-stopped networks: - laravel_network volumes: db_data: networks: laravel_network: driver: bridge
有了这些文件,我通常会在项目根目录运行:
docker-compose build
(首次构建或有Dockerfile修改时)docker-compose up -d
(启动所有服务,-d
表示后台运行)
容器启动后,进入app
容器执行Laravel命令:
3. docker-compose exec app composer install
(如果Dockerfile中没有安装或需要重新安装)
4. docker-compose exec app php artisan key:generate
5. docker-compose exec app php artisan migrate
然后访问http://localhost
,我的Laravel应用就应该跑起来了。这套流程走下来,效率真的提高不少。
为什么选择Docker部署Laravel?
我个人觉得,选择Docker部署Laravel,最直接的原因就是解决了那个经典的“在我机器上能跑”的问题。想想看,以前每次新项目启动,或者有新同事加入,光是配置PHP版本、Nginx、MySQL这些环境,就得耗费半天甚至一天时间,而且还总会遇到各种奇奇怪怪的版本冲突。我记得当初为了一个PHP扩展版本,折腾了整整一个下午,最后发现是系统库版本不对,那种无力感真是记忆犹新。
Docker的出现,就像是给每个项目都配了一个专属的、可复制的“运行环境盒子”。它把Laravel应用所需的一切(PHP、Nginx、数据库、Redis等)都打包在一起,无论在哪台机器上,只要有Docker,这个盒子就能原封不动地运行起来。这带来的好处是显而易见的:
- 环境一致性: 开发、测试、生产环境高度统一,大大减少了部署时的意外情况。
- 快速上手: 新成员加入团队,只需要拉取代码,运行几个Docker命令,就能立即投入开发,省去了繁琐的环境配置步骤。
- 依赖隔离: 不同的项目可以使用不同版本的PHP或数据库,互不干扰。比如,一个老项目还在用PHP 7.4,新项目已经用上PHP 8.2,Docker能轻松应对。
- 可移植性: 整个应用环境可以轻松地从一台机器迁移到另一台,甚至直接部署到云服务上。
- 简化扩展: 虽然Docker Compose本身不是生产环境的伸缩方案,但它为后续基于Kubernetes等容器编排工具的扩展打下了坚实的基础。
对我而言,这种“开箱即用”的感觉,以及项目环境的确定性,是任何其他部署方式都难以比拟的。它让我能更专注于代码本身,而不是纠结于环境问题。
Docker Compose配置Laravel项目有哪些最佳实践?
在配置docker-compose.yml
时,我积累了一些个人认为非常实用的“最佳实践”,它们能让你的Laravel项目在Docker环境中跑得更稳、更高效。
首先,服务分离是核心。不要试图把Nginx和PHP-FPM塞进同一个容器,那违背了容器“单一职责”的原则。每个服务(app
、web
、db
、redis
、queue
等)都应该有自己的独立容器。这样不仅便于管理和调试,也能让每个服务独立升级或扩展。比如,我的app
容器就只负责运行PHP-FPM,web
容器只跑Nginx,它们之间通过内部网络通信,互不干涉。
其次,合理使用数据卷(Volumes)。数据卷是实现数据持久化的关键。对于Laravel项目,我通常会挂载以下几个数据卷:
- 代码卷:
.:/var/www/html
将宿主机的项目代码同步到容器内。这在开发时非常方便,改了代码立即生效。 vendor
目录卷(可选但推荐):- /var/www/html/vendor
。这有点反直觉,因为我希望vendor
目录在容器内由Composer管理。但实际操作中,如果不挂载它,宿主机上可能会因为权限问题无法删除或修改vendor
目录下的文件。我的做法是,在Dockerfile
里安装Composer依赖,然后在docker-compose.yml
里明确挂载一个匿名卷到vendor
目录,这样宿主机上的vendor
目录就不会被影响,容器内的数据也独立。- 数据库数据卷:
db_data:/var/lib/mysql
。这是必须的,确保数据库数据在容器重启后不会丢失。 - Laravel的
storage
和bootstrap/cache
: 我倾向于直接在Dockerfile
中设置这些目录的权限,而不是单独挂载数据卷。因为这些目录的内容是应用运行时生成的,如果挂载数据卷,可能会遇到宿主机和容器之间的权限同步问题。当然,如果需要持久化存储上传文件等,可以考虑为storage/app/public
单独挂载数据卷。
再者,网络配置要清晰。Docker Compose默认会为所有服务创建一个桥接网络,让它们可以通过服务名互相通信。比如,我的Nginx容器可以通过app:9000
访问PHP-FPM服务。这比用IP地址要方便得多,也更具弹性。
还有,环境变量的管理。Laravel应用依赖.env
文件来配置数据库连接、缓存驱动等。在Docker Compose中,可以通过environment
字段直接设置环境变量,或者使用env_file
指定一个.env
文件。我通常会选择后者,因为它与Laravel的习惯保持一致,也方便本地开发。但需要注意的是,敏感信息(如数据库密码)在生产环境中应该使用更安全的秘密管理方案,而不是直接放在.env
文件里。
最后,健康检查(Healthchecks)。虽然在开发环境中不常用,但在生产环境中,为关键服务(如数据库)添加健康检查是非常有用的。它能让Docker知道服务是否真正“准备好了”,避免Nginx在数据库还没启动完成时就开始尝试连接,导致错误。
db: # ...其他配置 healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 5s retries: 5
这些实践,都是我在实际项目中摸索出来的,它们让Docker化的Laravel项目部署和维护变得更加顺畅。
Docker部署Laravel在生产环境中应注意哪些细节?
将Docker化的Laravel项目从开发环境推向生产环境,需要考虑的细节远比你想象的要多。在我看来,生产环境的部署不仅仅是让应用跑起来,更要关注其稳定性、性能、安全性和可维护性。
一个很重要的点是镜像优化。开发时我们可能不太在意镜像大小,但生产环境必须重视。我通常会采用多阶段构建(Multi-stage Builds)。这意味着我的Dockerfile
会有多个FROM
指令。第一个阶段用于构建应用(比如安装Composer依赖、编译前端资源),生成一个“构建产物”,第二个阶段则基于一个更轻量的基础镜像(比如php:8.2-fpm-alpine
),只复制最终的构建产物和运行所需的依赖。这样,最终的生产镜像会小很多,启动更快,攻击面也更小。例如,我不会把Composer本身留在生产镜像里。
# Dockerfile (简化版,展示多阶段构建概念) # Stage 1: Builder FROM composer:latest as builder WORKDIR /app COPY composer.json composer.lock ./ RUN composer install --no-dev --optimize-autoloader # Stage 2: Production FROM php:8.2-fpm-alpine WORKDIR /var/www/html COPY --from=builder /app/vendor /var/www/html/vendor COPY . . # ...其他安装PHP扩展、权限设置等 CMD ["php-fpm"]
资源限制也是生产环境的重点。在docker-compose.yml
中,你可以为每个服务设置CPU和内存限制(deploy.resources.limits
),这能防止某个服务耗尽宿主机的资源,影响其他应用。虽然Docker Compose在生产环境通常会被Kubernetes等更专业的编排工具取代,但在小规模部署或过渡期,这些限制依然有用。
日志策略必须明确。容器内的日志默认会输出到标准输出(stdout)和标准错误(stderr),Docker会捕获这些日志。这意味着你不需要在容器内配置复杂的日志文件。这很好,因为你可以利用Docker的日志驱动(如json-file
、syslog
、fluentd
等)将日志集中收集到外部日志管理系统(如ELK Stack、Grafana Loki)。确保Laravel的日志配置(config/logging.php
)是stack
或stderr
驱动,而不是写入文件。
秘密管理(Secrets Management)至关重要。数据库密码、API密钥等敏感信息绝不能直接写在docker-compose.yml
或Dockerfile
中。Docker Swarm和Kubernetes都有自己的秘密管理机制。如果只是用Docker Compose,可以考虑使用环境变量,但更安全的方式是使用外部工具,如HashiCorp Vault,或者在CI/CD流程中注入。
CI/CD集成是自动化部署的关键。每次代码提交后,应该触发CI/CD流水线,自动构建Docker镜像,运行测试,然后部署到生产环境。这大大减少了人工操作的错误,提高了部署效率和可靠性。我个人非常喜欢这种自动化流程,它让我能更专注于开发,而不是部署的繁琐。
别忘了Laravel自身的优化命令。在生产环境中,务必运行这些命令来提升性能:
php artisan config:cache
:缓存配置信息,减少每次请求时的文件读取。php artisan route:cache
:缓存路由信息,加速路由匹配。php artisan view:cache
:预编译Blade视图,减少运行时编译开销。composer dump-autoload --optimize
:优化Composer的自动加载器。
最后,监控和警报是不可或缺的。你需要实时了解应用和容器的运行状况,包括CPU、内存使用率、网络流量、错误日志等。Prometheus和Grafana是常见的组合,它们能帮助你及时发现问题并进行处理。同时,数据库备份策略也必须到位,这是任何生产应用最基本的保障。
这些细节,虽然看似繁琐,但却是确保Docker化Laravel应用在生产环境中稳定、高效运行的基石。忽视它们,迟早会遇到麻烦。
以上就是《Docker部署Laravel项目详细教程》的详细内容,更多关于docker,Laravel,容器化,Dockerfile,docker-compose.yml的资料请关注golang学习网公众号!

- 上一篇
- ZIP压缩怎么用?文件打包解压教程

- 下一篇
- Java函数式编程实战教程
-
- 文章 · php教程 | 4分钟前 |
- PhpStorm代码导航技巧快速定位方法
- 119浏览 收藏
-
- 文章 · php教程 | 8分钟前 |
- PHP自定义函数怎么创建?参数返回值详解
- 389浏览 收藏
-
- 文章 · php教程 | 16分钟前 |
- PHP手机号正则验证教程详解
- 387浏览 收藏
-
- 文章 · php教程 | 18分钟前 |
- PHPCMS与织梦广告管理对比评测
- 291浏览 收藏
-
- 文章 · php教程 | 27分钟前 |
- PhpStorm插件安装失败怎么解决
- 239浏览 收藏
-
- 文章 · php教程 | 28分钟前 |
- PHP中文分词实现方法详解
- 177浏览 收藏
-
- 文章 · php教程 | 34分钟前 |
- Laravel迁移外键重复怎么解决
- 116浏览 收藏
-
- 文章 · php教程 | 37分钟前 |
- PHP正则表达式使用全攻略
- 215浏览 收藏
-
- 文章 · php教程 | 46分钟前 |
- PHPCMSvs织梦栏目管理对比解析
- 112浏览 收藏
-
- 文章 · php教程 | 1小时前 |
- PHP远程执行命令的几种方法
- 251浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 扣子-Space(扣子空间)
- 深入了解字节跳动推出的通用型AI Agent平台——扣子空间(Coze Space)。探索其双模式协作、强大的任务自动化、丰富的插件集成及豆包1.5模型技术支撑,覆盖办公、学习、生活等多元应用场景,提升您的AI协作效率。
- 11次使用
-
- 蛙蛙写作
- 蛙蛙写作是一款国内领先的AI写作助手,专为内容创作者设计,提供续写、润色、扩写、改写等服务,覆盖小说创作、学术教育、自媒体营销、办公文档等多种场景。
- 12次使用
-
- CodeWhisperer
- Amazon CodeWhisperer,一款AI代码生成工具,助您高效编写代码。支持多种语言和IDE,提供智能代码建议、安全扫描,加速开发流程。
- 30次使用
-
- 畅图AI
- 探索畅图AI:领先的AI原生图表工具,告别绘图门槛。AI智能生成思维导图、流程图等多种图表,支持多模态解析、智能转换与高效团队协作。免费试用,提升效率!
- 54次使用
-
- TextIn智能文字识别平台
- TextIn智能文字识别平台,提供OCR、文档解析及NLP技术,实现文档采集、分类、信息抽取及智能审核全流程自动化。降低90%人工审核成本,提升企业效率。
- 65次使用
-
- PHP技术的高薪回报与发展前景
- 2023-10-08 501浏览
-
- 基于 PHP 的商场优惠券系统开发中的常见问题解决方案
- 2023-10-05 501浏览
-
- 如何使用PHP开发简单的在线支付功能
- 2023-09-27 501浏览
-
- PHP消息队列开发指南:实现分布式缓存刷新器
- 2023-09-30 501浏览
-
- 如何在PHP微服务中实现分布式任务分配和调度
- 2023-10-04 501浏览