feat(stack): 所有 Docker 模式集成 XHProf 性能分析

在 docker-dev/docker-dev-sync/docker-serve/full 四个模式中集成 XHProf
性能分析能力,默认不启用(--profile xhprof 按需开启),零侵入不改
业务代码和 run.sh。

核心组件:
- source/docker/xhprof-bootstrap.php: 采集器初始化(auto_prepend_file)
- source/docker/xhgui-config.php: XHGui 认证配置(Basic Auth)+ PDO 存储
- 各 Dockerfile: 安装 PECL xhprof 扩展 + php-profiler 到 /opt/xhprof/
- 各 docker-compose: 新增 xhgui 服务(profiles: xhprof),端口 8142

存储方案:PDO MySQL(复用现有 MySQL),避免 MongoDB PHP 驱动兼容性问题。
docker-dev/docker-dev-sync 开箱即用;docker-serve/full 需配置 XHGUI_PDO_DSN。

认证:HTTP Basic Auth,默认 admin/xhgui123,环境变量可覆盖。
采集控制:XHPROF_ENABLE 环境变量 + cookie _profiler 强制触发 + 1% 采样。
Dockerfile.base 同步新增 xhprof 扩展(框架作者需重建推送基础镜像)。
This commit is contained in:
augushong
2026-08-09 09:07:10 +08:00
parent af0988118a
commit e0e2580646
12 changed files with 319 additions and 4 deletions

View File

@@ -39,14 +39,71 @@ cd source/stack/docker-dev-myproject && docker compose up -d
| 模式 | 说明 |
|------|------|
| `default` | 默认基线,仓库根目录 `php think run`,无 Docker 文件 |
| `docker-serve` | Docker 部署模式基于基础镜像nginx + php-fpm |
| `docker-dev` | Docker 开发模式nginx + php-fpm + MySQL + Redis + phpMyAdmin + Xdebug |
| `docker-dev-sync` | Docker 开发模式 - Windows I/O 优化rsync 同步,避免 bind mount 慢速问题) |
| `full` | 完整服务栈(规划中),从 PHP 镜像从头构建 |
| `docker-serve` | Docker 部署模式基于基础镜像nginx + php-fpm + XHProf |
| `docker-dev` | Docker 开发模式nginx + php-fpm + MySQL + Redis + phpMyAdmin + Xdebug + XHProf |
| `docker-dev-sync` | Docker 开发模式 - Windows I/O 优化rsync 同步,避免 bind mount 慢速问题) + XHProf |
| `full` | 完整服务栈(规划中),从 PHP 镜像从头构建 + XHProf |
| `author` | 框架作者维护工具(基础镜像构建、发布脚本等) |
> `author` 为框架作者专用,使用者一般不需要。
## XHProf 性能分析(可选)
docker-dev / docker-dev-sync / docker-serve / full 模式内置了 XHProf 性能分析能力,默认不启用,完全不影响现有行为。采集数据存储在 MySQL 中PDO 方式docker-dev / docker-dev-sync 开箱即用docker-serve / full 需配置 XHGUI_PDO_DSN 环境变量指向可用的 MySQL。
### 启用方式
```bash
# 在模式目录中,加 --profile xhprof 启动
cd source/stack/docker-dev
XHPROF_ENABLE=true docker compose --profile xhprof up -d
```
或者在 `.env` 中设置 `XHPROF_ENABLE=true`,然后:
```bash
docker compose --profile xhprof up -d
```
### 查看性能报告
浏览器打开 `http://localhost:8142`,输入 Basic Auth 用户名密码(默认 `admin` / `xhgui123`)。
### 认证配置
通过环境变量覆盖默认密码(在 `.env` 或 docker-compose 命令行设置):
```env
XHGUI_AUTH_USER=myuser
XHGUI_AUTH_PASS=mypassword
```
### 存储配置
默认使用 PDO MySQL 存储(复用 docker-dev 的 MySQL。通过环境变量自定义
```env
XHGUI_PDO_DSN=mysql:host=mysql;dbname=ulthon;charset=utf8mb4
XHGUI_PDO_USER=root
XHGUI_PDO_PASS=root
```
docker-serve / full 模式没有内置 MySQL需要设置 `XHGUI_PDO_DSN` 指向可用的 MySQL 实例。
### 手动触发采集
默认 1% 采样率。需要强制采集某个请求时,浏览器请求带 cookie `_profiler=1`
### 端口说明
| 端口 | 服务 | 说明 |
|------|------|------|
| 8142 | XHGui | 性能分析报告界面 |
### 默认行为
不加 `--profile xhprof`XHGui 服务不启动,行为与未集成 XHProf 完全一致。
## default 目录规则(强约束)
- `source/stack/default/` 必须与代码库默认行为一致(`php think run`,不依赖 Docker

View File

@@ -26,6 +26,7 @@ RUN install-php-extensions event
RUN install-php-extensions imagick
RUN install-php-extensions zip
RUN install-php-extensions pcntl
RUN install-php-extensions xhprof
# 清理默认 Nginx 配置
RUN rm /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

View File

@@ -27,6 +27,7 @@ RUN install-php-extensions imagick
RUN install-php-extensions zip
RUN install-php-extensions pcntl
RUN install-php-extensions xdebug
RUN install-php-extensions xhprof
# Clean default Nginx config
RUN rm /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
@@ -62,6 +63,17 @@ RUN rm -rf /var/www/html/source/docker && ln -sf /var/www/html/source/stack/dock
# Generate autoloader (without --no-dev optimizations)
RUN composer dump-autoload
# XHProf: 安装 php-profiler 到独立目录(避免 rsync 同步覆盖)
RUN mkdir -p /opt/xhprof \
&& cd /opt/xhprof \
&& composer require perftools/php-profiler
# XHProf: 复制采集器 bootstrap全局配置不受 rsync 同步影响)
COPY source/docker/xhprof-bootstrap.php /opt/xhprof/xhprof-bootstrap.php
# XHProf: 配置 auto_prepend_filezzz 前缀确保最后加载)
RUN echo 'auto_prepend_file = /opt/xhprof/xhprof-bootstrap.php' > /usr/local/etc/php/conf.d/zzz-xhprof.ini
# Internal install composer and dependencies, comment out if not needed
# RUN install-php-extensions @composer

View File

@@ -17,6 +17,9 @@ services:
environment:
# Sync polling interval in seconds (default: 3)
- SYNC_INTERVAL=${SYNC_INTERVAL:-3}
- XHPROF_ENABLE=${XHPROF_ENABLE:-false}
- XHGUI_UPLOAD_URL=http://xhgui:80/run/import
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
extra_hosts:
- "host.docker.internal:host-gateway"
depends_on:
@@ -57,3 +60,21 @@ services:
depends_on:
mysql:
condition: service_healthy
xhgui:
image: xhgui/xhgui:0.24.x
restart: unless-stopped
profiles: ["xhprof"]
ports:
- "8142:80"
volumes:
# 挂载全局认证配置Basic Auth
- ../../../source/docker/xhgui-config.php:/var/www/xhgui/config/config.php
environment:
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
# Basic Auth 认证(默认 admin/xhgui123通过 .env 或环境变量覆盖)
- XHGUI_AUTH_USER=${XHGUI_AUTH_USER:-admin}
- XHGUI_AUTH_PASS=${XHGUI_AUTH_PASS:-xhgui123}
depends_on:
mysql:
condition: service_healthy

View File

@@ -27,6 +27,7 @@ RUN install-php-extensions imagick
RUN install-php-extensions zip
RUN install-php-extensions pcntl
RUN install-php-extensions xdebug
RUN install-php-extensions xhprof
# Clean default Nginx config
RUN rm /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
@@ -65,6 +66,17 @@ RUN rm -rf /var/www/html/source/docker \
# Generate autoloader (without --no-dev optimizations)
RUN composer dump-autoload
# XHProf: 安装 php-profiler 到独立目录(避免 bind mount 覆盖 /var/www/html
RUN mkdir -p /opt/xhprof \
&& cd /opt/xhprof \
&& composer require perftools/php-profiler
# XHProf: 复制采集器 bootstrap全局配置不受 bind mount 影响)
COPY source/docker/xhprof-bootstrap.php /opt/xhprof/xhprof-bootstrap.php
# XHProf: 配置 auto_prepend_filezzz 前缀确保最后加载)
RUN echo 'auto_prepend_file = /opt/xhprof/xhprof-bootstrap.php' > /usr/local/etc/php/conf.d/zzz-xhprof.ini
# Internal install composer and dependencies, comment out if not needed
# RUN install-php-extensions @composer

View File

@@ -14,6 +14,10 @@ services:
- ../../..:/var/www/html
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
- XHPROF_ENABLE=${XHPROF_ENABLE:-false}
- XHGUI_UPLOAD_URL=http://xhgui:80/run/import
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
depends_on:
mysql:
condition: service_healthy
@@ -52,3 +56,21 @@ services:
depends_on:
mysql:
condition: service_healthy
xhgui:
image: xhgui/xhgui:0.24.x
restart: unless-stopped
profiles: ["xhprof"]
ports:
- "8142:80"
volumes:
# 挂载全局认证配置Basic Auth
- ../../../source/docker/xhgui-config.php:/var/www/xhgui/config/config.php
environment:
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
# Basic Auth 认证(默认 admin/xhgui123通过 .env 或环境变量覆盖)
- XHGUI_AUTH_USER=${XHGUI_AUTH_USER:-admin}
- XHGUI_AUTH_PASS=${XHGUI_AUTH_PASS:-xhgui123}
depends_on:
mysql:
condition: service_healthy

View File

@@ -1,6 +1,9 @@
ARG BASE_IMAGE=ulthon/ulthon_admin-base:latest
FROM ${BASE_IMAGE}
# XHProf 扩展(若基础镜像已含则跳过)
RUN install-php-extensions xhprof
# 设置工作目录
WORKDIR /var/www/html
@@ -17,6 +20,17 @@ RUN rm -rf /var/www/html/source/docker && ln -sf /var/www/html/source/stack/dock
# 生成自动加载文件
RUN composer dump-autoload --optimize --no-dev --classmap-authoritative
# XHProf: 安装 php-profiler 到独立目录
RUN mkdir -p /opt/xhprof \
&& cd /opt/xhprof \
&& composer require perftools/php-profiler --no-dev
# XHProf: 复制采集器 bootstrap全局配置不受 bind mount 影响)
COPY source/docker/xhprof-bootstrap.php /opt/xhprof/xhprof-bootstrap.php
# XHProf: 配置 auto_prepend_filezzz 前缀确保最后加载)
RUN echo 'auto_prepend_file = /opt/xhprof/xhprof-bootstrap.php' > /usr/local/etc/php/conf.d/zzz-xhprof.ini
VOLUME /var/www/html/runtime
VOLUME /var/www/html/public/storage
VOLUME /var/www/html/public/build

View File

@@ -18,5 +18,25 @@ services:
# - ./public/storage:/var/www/html/public/storage
# - ./public/build:/var/www/html/public/build
# - ./storage:/var/www/html/storage
environment:
- XHPROF_ENABLE=${XHPROF_ENABLE:-false}
- XHGUI_UPLOAD_URL=http://xhgui:80/run/import
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
extra_hosts:
- "host.docker.internal:host-gateway"
xhgui:
image: xhgui/xhgui:0.24.x
restart: always
profiles: ["xhprof"]
ports:
- "8142:80"
volumes:
# 挂载全局认证配置Basic Auth
- ../../../source/docker/xhgui-config.php:/var/www/xhgui/config/config.php
environment:
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
# Basic Auth 认证(默认 admin/xhgui123通过 .env 或环境变量覆盖)
- XHGUI_AUTH_USER=${XHGUI_AUTH_USER:-admin}
- XHGUI_AUTH_PASS=${XHGUI_AUTH_PASS:-xhgui123}
# PDO 存储:需配置 XHGUI_PDO_DSN 指向 MySQLdocker-serve 无内置 MySQL

View File

@@ -26,6 +26,7 @@ RUN install-php-extensions event
RUN install-php-extensions imagick
RUN install-php-extensions zip
RUN install-php-extensions pcntl
RUN install-php-extensions xhprof
# 清理默认 Nginx 配置
RUN rm /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default
@@ -61,6 +62,17 @@ RUN rm -rf /var/www/html/source/docker && ln -sf /var/www/html/source/stack/full
# 生成自动加载文件
RUN composer dump-autoload --optimize --no-dev --classmap-authoritative
# XHProf: 安装 php-profiler 到独立目录
RUN mkdir -p /opt/xhprof \
&& cd /opt/xhprof \
&& composer require perftools/php-profiler --no-dev
# XHProf: 复制采集器 bootstrap全局配置不受 bind mount 影响)
COPY source/docker/xhprof-bootstrap.php /opt/xhprof/xhprof-bootstrap.php
# XHProf: 配置 auto_prepend_filezzz 前缀确保最后加载)
RUN echo 'auto_prepend_file = /opt/xhprof/xhprof-bootstrap.php' > /usr/local/etc/php/conf.d/zzz-xhprof.ini
# 内部安装compsoer并安装依赖如果不需要可以注释掉
# RUN install-php-extensions @composer

View File

@@ -18,5 +18,25 @@ services:
# - ./public/storage:/var/www/html/public/storage
# - ./public/build:/var/www/html/public/build
# - ./storage:/var/www/html/storage
environment:
- XHPROF_ENABLE=${XHPROF_ENABLE:-false}
- XHGUI_UPLOAD_URL=http://xhgui:80/run/import
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
extra_hosts:
- "host.docker.internal:host-gateway"
xhgui:
image: xhgui/xhgui:0.24.x
restart: always
profiles: ["xhprof"]
ports:
- "8142:80"
volumes:
# 挂载全局认证配置Basic Auth
- ../../../source/docker/xhgui-config.php:/var/www/xhgui/config/config.php
environment:
- XHGUI_UPLOAD_TOKEN=${XHGUI_UPLOAD_TOKEN:-ulthon-admin-xhprof}
# Basic Auth 认证(默认 admin/xhgui123通过 .env 或环境变量覆盖)
- XHGUI_AUTH_USER=${XHGUI_AUTH_USER:-admin}
- XHGUI_AUTH_PASS=${XHGUI_AUTH_PASS:-xhgui123}
# PDO 存储:需配置 XHGUI_PDO_DSN 指向 MySQLdocker-serve 无内置 MySQL