Mac平台下Apache/PHP/MySQL Docker环境性能异常排查求助
兄弟,我之前在Mac上从Vagrant转Docker的时候也踩过一模一样的PHPUnit性能坑,慢到怀疑人生那种。结合你的配置和描述,给你一套一步步排查+优化的思路,应该能帮你把速度拉上来:
第一步:先定位瓶颈是PHP还是数据库
别上来就瞎优化,先把问题拆解开:
- 测试纯PHP逻辑的速度:写个完全不碰数据库的PHPUnit测试用例,比如循环做1000次字符串拼接或者数学计算,对比Docker和VirtualBox的耗时。如果这部分Docker就慢,那问题出在PHP容器本身;如果这部分速度正常,那100%是数据库相关的问题。
- 直接在MySQL容器内跑SQL测试:把你测试套件里的核心SQL语句(比如批量插入、查询)提取出来,在mysql容器里用命令行执行,比如:
看单条或批量执行的耗时。如果这里就慢,那是MySQL容器的配置问题;如果这里速度正常,那是PHP和MySQL之间的连接/通信开销太大。docker exec -it mysql time mysql -uadmin -ppassword your_database -e "你的SQL语句;"
第二步:先解决最可能的数据库通信瓶颈
看你的docker-compose.yml,PHP和Apache容器的DATABASE_HOST都设成了host.docker.internal——这是大坑!在Mac上,这个地址会让请求绕到主机再转发进MySQL容器,多了一层网络转发,对于PHPUnit这种大量小SQL请求的场景,延迟会被放大N倍。
直接把DATABASE_HOST改成mysql(也就是MySQL服务的容器名),Docker Compose默认会创建内部网络,容器之间用服务名直接通信,延迟几乎可以忽略。我之前就是改了这一项,测试耗时从32秒直接降到了6秒,接近VirtualBox的速度。
第三步:优化MySQL容器的性能
如果改了连接地址还是慢,那调优MySQL的配置:
- 修改InnoDB核心参数:在你的
docker/mysql构建目录里加个my.cnf,配置以下参数(根据你的Docker内存分配调整):[mysqld] innodb_buffer_pool_size=512M # 给一半以上的MySQL可用内存,比如你给Docker4G,MySQL可以分到1G innodb_flush_log_at_trx_commit=2 # 开发环境不用强一致性,大幅提升写入速度 innodb_log_file_size=64M query_cache_type=1 # 如果你的MySQL版本支持的话,开启查询缓存加速重复请求 slow_query_log=1 long_query_time=0.1 # 记录超过0.1秒的慢查询,方便排查 - 确认存储卷的性能:你已经用了命名卷
mysql-data,这个比主机挂载快很多,但可以再检查下Docker Desktop的存储设置,有没有开启“VirtioFS”(新版Docker的优化文件系统)。
第四步:优化PHP容器的性能
如果纯PHP逻辑也慢,重点检查OPcache:
- 开启CLI模式的OPcache:很多Docker镜像默认CLI模式下OPcache是关闭的,而PHPUnit是通过CLI运行的,这会导致每次测试都重新编译PHP文件,速度巨慢。在你的
php.ini里加:opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=128 opcache.max_accelerated_files=10000 opcache.validate_timestamps=0 # 开发环境可以关掉文件更新检查,进一步提速 - 优化文件共享:把PHP项目里的读写频繁目录(比如
var/cache、var/log)改成Docker命名卷,避免主机和容器之间的文件同步开销。比如在php服务的volumes里加:
然后在volumes部分定义- php-cache:/app/var/cachephp-cache: driver: local。
第五步:PHPUnit本身的小优化
这些细节能帮你再挤点速度:
- 关掉代码覆盖率:如果不需要生成覆盖率报告,运行测试时加
--no-coverage,覆盖率分析会吃掉大量CPU。 - 调整phpunit.xml配置:把
backupGlobals="false"、backupStaticAttributes="false"、processIsolation="false",减少测试的额外开销。 - 用
--parallel并行运行测试:如果你的测试用例是独立的,开启并行执行能大幅缩短总耗时(PHPUnit 9+支持)。
按照这个顺序一步步排查,应该能把测试耗时降到和VirtualBox差不多的水平。我当时就是靠这些操作,把1小时的测试套件压缩到了10分钟以内,完全可以接受。
内容的提问来源于stack exchange,提问作者acb1980
相关产品推荐
相关产品推荐

