如何用Docker部署PHP项目:从零开始的容器化实战指南
目录导读
- 为什么选择Docker部署PHP项目?
- 环境准备与核心概念解析
- 编写Dockerfile:构建PHP+Apache/Nginx镜像
- 使用docker-compose编排多容器(PHP+MySQL+Redis)
- 项目部署与数据持久化配置
- 常见问题与解决方案(FAQ)
- 性能优化与安全最佳实践
为什么选择Docker部署PHP项目?
在传统开发中,PHP项目常因环境差异导致“在我机器上能运行”的尴尬,Docker通过容器化技术,将PHP应用及其依赖(如扩展、Web服务器、数据库)打包成独立单元,确保开发、测试、生产环境一致,根据2025年Stack Overflow调查,超过67%的开发者已采用容器化部署,其中PHP项目占比显著增长。

核心优势:
- 环境隔离:不同项目使用不同PHP版本(如7.4、8.2)互不干扰
- 快速迭代:修改代码后秒级重启容器,无需重装系统
- 资源节约:相比虚拟机,容器共享宿主机内核,内存占用降低40%
适用场景: Laravel、Symfony、ThinkPHP等主流框架,以及WordPress、Drupal等内容管理系统。
环境准备与核心概念解析
你需要:
- 已安装Docker Desktop(Windows/Mac)或Docker Engine(Linux)
- 对PHP基本语法和命令行熟悉
- 一个待部署的PHP项目(如简单的
index.php输出phpinfo())
关键概念:
- ✅ 镜像(Image):只读模板,如
php:8.2-apache(含PHP和Apache) - ✅ 容器(Container):镜像的运行实例,可读写
- ✅ 数据卷(Volume):持久化保存数据库文件和上传资源
- ✅ Docker Compose:批量管理多个容器(PHP+MySQL+Nginx)
编写Dockerfile:构建PHP+Apache/Nginx镜像
以PHP + Apache为例,创建项目根目录下的Dockerfile:
# 使用官方PHP 8.2 Apache镜像 FROM php:8.2-apache # 安装常用PHP扩展 RUN docker-php-ext-install pdo_mysql mysqli # 启用Apache重写(支持Laravel等框架) RUN a2enmod rewrite # 复制项目代码到容器默认目录 COPY . /var/www/html/ # 设置目录权限(生产环境注意安全) RUN chown -R www-data:www-data /var/www/html
构建镜像:
docker build -t my-php-app .
运行容器:
docker run -d -p 8080:80 --name php-demo my-php-app
访问http://localhost:8080即可看到项目运行。
若需使用Nginx: 采用Nginx+PHP-FPM组合,需两个Dockerfile或直接使用官方镜像php:8.2-fpm。
使用docker-compose编排多容器(PHP+MySQL+Redis)
实际项目通常需要数据库,创建docker-compose.yml:
version: '3.8'
services:
php:
build: .
ports:
- "8080:80"
volumes:
- ./src:/var/www/html # 代码热更新
depends_on:
- db
- redis
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: myapp
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
mysql_data:
启动所有服务:
docker-compose up -d
关键说明:
volumes挂载使本地代码修改即时生效(开发模式)depends_on保证数据库先启动- 容器间可通过服务名互通(如PHP中连接MySQL用
host=db)
项目部署与数据持久化配置
生产环境差异:
- 移除代码热挂载,改为镜像内打包
- 使用环境变量管理数据库密码(而非硬编码)
优化版生产Dockerfile:
FROM php:8.2-apache RUN docker-php-ext-install pdo_mysql opcache COPY --chown=www-data:www-data . /var/www/html/ # 设置生产配置 RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
数据持久化技巧:
- MySQL数据:使用命名卷(
mysql_data),删除容器后数据保留 - 上传文件:单独挂载
volumes:- ./uploads:/var/www/html/uploads - 日志文件:使用
docker logs或挂载日志目录
常见问题与解决方案(FAQ)
Q1:容器启动后访问报错“404 Not Found”?
A:检查DocumentRoot设置,若使用Laravel,需配置Apache虚拟主机指向public目录,或在Dockerfile中添加:
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
Q2:PHP连接MySQL失败,提示“Host not allowed”? A:容器内MySQL需允许远程连接,在Compose文件中为MySQL添加:
environment: MYSQL_ROOT_HOST: '%' # 允许所有主机
或指定PHP容器IP(生产更安全)。
Q3:如何修改PHP配置(如上传文件大小)?
A:在Dockerfile或Compose中自定义php.ini:
php:
volumes:
- ./php.ini:/usr/local/etc/php/php.ini
其中php.ini包含upload_max_filesize = 20M。
Q4:容器重启后数据丢失?
A:确保数据库使用了卷(volume)而非临时存储,检查docker-compose.yml中是否有 volumes: - mysql_data:/var/lib/mysql。
性能优化与安全最佳实践
优化建议:
- 使用PHP 8.2+的OPcache扩展,提升代码执行速度(已在生产Dockerfile中启用)
- 使用Alpine基础镜像缩小体积(如
php:8.2-fpm-alpine) - 生产环境结合Nginx反向代理+PHP-FPM,比Apache资源占用低30%
安全措施:
- 不要以root用户运行容器(使用
www-data) - 敏感信息(如DB密码)使用docker secrets或.env文件
- 定期扫描镜像漏洞:
docker scan my-php-app - 限制容器网络:仅暴露必要端口
扩展阅读: 若需部署ThinkPHP框架,需开启URL重写;WordPress可配合官方镜像wordpress:php8.2-apache快速搭建。
通过以上步骤,你可以实现从本地开发到生产环境的无缝迁移,Docker不仅解决了环境一致性问题,更让团队协作、自动部署(CI/CD)变得简单,当遇到新问题时,记住核心思路:将PHP应用视为无状态容器,所有持久化数据交给卷,所有配置交给环境变量。