📖 前言:核心架构理念
在 1Panel 容器化环境中,必须打破传统宝塔(LNMP)的思维定势:
- 网络孤岛:PHP 容器(运行环境)与 MySQL/Redis(应用商店)默认网络不通,需手动组网。
- Swoole 特性:常驻内存服务。修改
.env或config必须重启进程;单纯刷新浏览器无效。 - 文件映射:1Panel 文件管理看到的路径是宿主机路径,与容器内部路径不同,修改配置需找对入口。
🏗️ 第一阶段:基础设施搭建
1.1 打通容器网络
PHP 容器无法通过 127.0.0.1 连接数据库,必须加入 Docker 网络。
Bash
# SSH 终端执行
# 1. 自动获取 Redis 所在网络
NET_NAME=$(docker inspect -f '{{range $k,$v := .NetworkSettings.Networks}}{{$k}}{{end}}' 1Panel-redis-lIVN)
# 2. 将 PHP 容器加入该网络
docker network connect $NET_NAME PHP_8_0
# 3. 验证 (用 PHP 脚本测试连接)
docker exec -u 0 PHP_8_0 php -r '$r=new Redis(); $r->connect("1Panel-redis-lIVN",6379)?print("✅ Pass\n"):print("❌ Fail\n");'
1.2 纯净版环境配置 (.env)
ThinkPHP 对 .env 格式要求极严。
- 严禁:行尾加中文注释、使用特殊符号(如括号)。
- 必须:
HOST=0.0.0.0(允许外部 Nginx 连接)。 - 必须:使用容器真名(如
1Panel-mysql-DX5i)而非 IP。
⚙️ 第二阶段:核心服务配置
2.1 数据库兼容性修正 (解决 GROUP BY 报错) 【新增重点】
现象:后台报 SQLSTATE[42000]: ... incompatible with sql_mode=only_full_group_by。
原因:MySQL 5.7/8.0 默认开启严格模式,不兼容旧式聚合查询。
操作步骤:
- 1Panel -> 文件 -> 路径:
/opt/1panel/apps/mysql/mysql/conf/。 - 编辑
my.cnf,在[mysqld]块底部添加:Ini, TOMLsql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION - 1Panel -> 容器 -> 重启 MySQL 容器。
2.2 Supervisor 守护进程
避坑:CRMEB Pro 启动命令不带 start 参数。
配置文件 (/etc/supervisor/conf.d/crmeb.conf):
Ini, TOML
[program:crmeb_pro]
# 使用 docker exec 穿透宿主机
command=/usr/bin/docker exec -u 0 -w /www/sites/1gv.cn/index PHP_8_0 php think swoole
process_name=%(program_name)s
numprocs=1
autostart=true
autorestart=true
startsecs=3
stopasgroup=true
killasgroup=true
stdout_logfile=/www/sites/1gv.cn/index/runtime/supervisor_out.log
stderr_logfile=/www/sites/1gv.cn/index/runtime/supervisor_err.log
🌐 第三阶段:Nginx 网关配置 (生产环境终极版)
此配置解决了 Iframe 页面装修白屏、静态资源 404、502 错误。
关键修正点:
- Upstream:指向 PHP 容器真实 IP(
docker inspect获取)。 - Iframe 支持:静态资源规则加入
html|htm并添加X-Frame-Options SAMEORIGIN。 - 动静分离:静态资源由 Nginx 处理,动态请求透传给 Swoole。
Nginx
upstream crmeb_swoole {
server 172.18.0.4:20199; # ⚠️ 替换为你的 PHP 容器真实 IP
keepalive 256;
}
server {
listen 80;
listen 443 ssl http2;
server_name 1gv.cn;
# 1Panel 真实路径
root /www/sites/1gv.cn/index/public;
index index.php index.html;
# SSL 配置省略...
# 【新增】页面装修/Iframe 兼容配置
# 必须包含 html/htm,否则装修预览框会 404 或被拦截
location ~* \.(jpg|jpeg|png|gif|ico|css|js|html|htm|woff2|woff|ttf|svg|eot)$ {
expires 7d;
access_log off;
# 允许同源 iframe 嵌套
add_header X-Frame-Options SAMEORIGIN always;
try_files $uri @swoole;
}
# 上传目录
location ^~ /uploads/ {
expires 7d;
}
# 核心转发
location / {
proxy_pass http://crmeb_swoole;
proxy_http_version 1.1;
proxy_read_timeout 360s;
# WebSocket 必须
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
}
location @swoole {
proxy_pass http://crmeb_swoole;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
💻 第四阶段:运维与二次开发 (DevOps)
4.1 注入快捷指令 (提高 10 倍效率)
在 SSH 执行一次,永久生效。
Bash
# 写入 ~/.bashrc
echo "alias dev-reload='docker exec -u 0 -w /www/sites/1gv.cn/index PHP_8_0 php think swoole reload'" >> ~/.bashrc
# 核弹级重启:清理缓存 + 重启 Supervisor
echo "alias dev-restart='docker exec -u 0 -w /www/sites/1gv.cn/index PHP_8_0 rm -rf runtime/cache runtime/temp runtime/log runtime/dbtables && supervisorctl restart crmeb_pro && sleep 2 && supervisorctl status crmeb_pro'" >> ~/.bashrc
# 查看实时日志
echo "alias dev-log='tail -f /www/sites/1gv.cn/index/runtime/supervisor_err.log'" >> ~/.bashrc
source ~/.bashrc
4.2 常用命令对照表
| 场景 | 快捷指令 | 说明 |
修改 .env 或 config | dev-restart | 必须完全重启进程 |
| 安装 Composer 包 | dev-restart | 加载新类库 |
| 修改 PHP 业务逻辑 | dev-reload | 平滑重载,无需断线 |
| 网站 502 / 白屏 | dev-log | 查看报错堆栈 |
| 数据库 Access Denied | dev-restart | 必须清理旧连接池缓存 |
🚑 故障排查终极手册 (Troubleshooting)
| 现象 | 报错关键词 | 根本原因 | 解决方案 |
| 后台/移动端报错 | SQLSTATE[HY000] [1045] Access denied | Swoole 连接池复用了旧密码的脏连接 | 执行 dev-restart (含清理缓存) |
| 页面装修白屏 | 499 或 Loading chunk failed | Nginx 拦截了 .html 或禁止 Iframe | 修改 Nginx 静态规则,加 html 支持和 X-Frame-Options |
| 统计图表不显示 | GROUP BY clause... | MySQL 严格模式 | 修改 my.cnf 去掉 ONLY_FULL_GROUP_BY |
| Swoole 无法启动 | Too many arguments | 启动命令多了 start | 修改 Supervisor 去掉参数 |
| 502 Bad Gateway | Connection refused | Nginx 连不上 PHP 容器 | 检查 Nginx 配置的 upstream IP 是否正确 |
| 前端 JS 报错 | Cannot read properties of undefined | 后端接口挂了 (500/404) | F12 查看 Network 红色请求响应内容,通常是上述数据库或权限问题 |
| 上传图片失败 | Permission denied | 容器用户无权写入宿主机挂载目录 | chmod -R 777 public/uploads |

