SEO 关键词: 1Panel, CRMEB Pro, Swoole, Docker 容器通信, Nginx 502, Supervisor, ThinkPHP, 运维部署, 二次开发
适用场景:1Panel v2.x 容器化环境 + CRMEB Pro v3.x (Swoole)
核心痛点:解决容器网络隔离、配置加载失败、Nginx 502/404、开发调试繁琐问题。
第一章:基础架构搭建 (只做一次)
在 1Panel 中,PHP 容器(运行环境)默认无法连接 Redis/MySQL 容器(应用商店)。必须手动打通网络。
1.1 容器网络“搭桥”
不要指望 127.0.0.1,必须让 PHP 容器加入 Redis 所在的网络。
Bash
# === 复制以下命令块执行 ===
# 1. 获取 Redis 所在网络名称 (自动侦测)
NET_NAME=$(docker inspect -f '{{range $k,$v := .NetworkSettings.Networks}}{{$k}}{{end}}' 1Panel-redis-lIVN)
echo "侦测到网络: $NET_NAME"
# 2. 将 PHP 容器加入该网络
docker network connect $NET_NAME PHP_8_0 2>/dev/null || echo "网络已连通"
# 3. 验证连通性 (必须看到 Connection established 或类似成功提示)
docker exec -u 0 PHP_8_0 php -r '
$r=new Redis();
try{
$r->connect("1Panel-redis-lIVN", 6379);
echo "✅ Redis 连接成功!\n";
} catch(Exception $e){
echo "❌ 失败: ".$e->getMessage()."\n";
}
'
第二章:标准配置文件 (复制即用)
2.1 环境配置 .env (1Panel 网页端修改)
- 文件路径:
/www/sites/1gv.cn/index/.env - 严禁事项:禁止在值后面加中文注释!禁止加括号!
Ini, TOML
[APP]
HOST=0.0.0.0
PORT=20199
[DATABASE]
DRIVER=mysql
TYPE=mysql
# 必须填容器真名,不能填 127.0.0.1
HOSTNAME=1Panel-mysql-DX5i
DATABASE=crmeb_pro
USERNAME=crmeb_user
# 👇 请替换为你的真实密码
PASSWORD=你的数据库密码
HOSTPORT=3306
CHARSET=utf8
DEBUG=true
[REDIS]
# 必须填容器真名
HOSTNAME=1Panel-redis-lIVN
PORT=6379
# 👇 请替换为你的真实密码
PASSWORD=你的Redis密码
SELECT=0
[QUEUE]
LISTEN_NAME=
BATCH_LISTEN_NAME=
2.2 守护进程配置 Supervisor (SSH 端修改)
- 文件路径:
/etc/supervisor/conf.d/crmeb.conf - 核心逻辑:使用
docker exec穿透;去掉start参数。
Bash
# === 复制以下命令生成配置文件 ===
cat > /etc/supervisor/conf.d/crmeb.conf <<EOF
[program:crmeb_pro]
# ✅ 核心命令:无 start 参数,使用 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 startretries=10 stopsignal=QUIT stopasgroup=true killasgroup=true # 日志直接输出到项目目录,方便在 1Panel 网页查看 stdout_logfile=/www/sites/1gv.cn/index/runtime/supervisor_out.log stderr_logfile=/www/sites/1gv.cn/index/runtime/supervisor_err.log stdout_logfile_maxbytes=10MB stderr_logfile_maxbytes=10MB EOF # === 重新加载配置 === supervisorctl update
第三章:二次开发效率工具 (必装)
你提到需要“频繁重启”和“方便快捷”。每次都敲长命令是低效的。请在 SSH 终端设置以下 快捷指令 (Alias)。
3.1 注入快捷命令
Bash
# === 复制以下命令块执行 ===
# 1. 重载代码 (Dev Reload)
# 适用场景:修改了 PHP 业务代码 (Controller/Service),想不中断连接生效
echo "alias dev-reload='docker exec -u 0 -w /www/sites/1gv.cn/index PHP_8_0 php think swoole reload'" >> ~/.bashrc
# 2. 彻底重启 (Dev Restart) - 最常用!
# 适用场景:修改了 .env、config、安装了新扩展、或者单纯想重置环境
# 逻辑:清空缓存 -> 重启 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 && supervisorctl restart crmeb_pro && sleep 2 && supervisorctl status crmeb_pro'" >> ~/.bashrc
# 3. 查看报错 (Dev Log)
# 适用场景:服务启动失败,想看为什么
echo "alias dev-log='tail -f /www/sites/1gv.cn/index/runtime/supervisor_err.log'" >> ~/.bashrc
# 4. 进入容器 (Dev Shell)
# 适用场景:需要进去执行 composer 或 php 命令
echo "alias dev-shell='docker exec -it -u 0 -w /www/sites/1gv.cn/index PHP_8_0 /bin/sh'" >> ~/.bashrc
# 使配置立即生效
source ~/.bashrc
echo "✅ 开发快捷键已安装!"
echo "输入 dev-restart 即可一键重启"
echo "输入 dev-log 可实时查看报错"
3.2 二次开发常用操作表
| 你的操作 | 你应该执行的命令 | 原理 |
修改了 .env 文件 | dev-restart | 必须重启进程才能读取新环境变量 |
修改了 config/*.php | dev-restart | 必须重启进程才能读取新配置 |
| 修改了 PHP 逻辑代码 | dev-reload (或等待热更) | 平滑重载 Worker 进程,用户无感知 |
| 网站突然打不开 (502) | dev-log | 查看报错日志,通常是代码语法错误 |
| 安装了 composer 包 | dev-restart | 需要重启以加载新类库 |
第四章:Nginx 生产环境标准配置 (The Production Config)
注意: 安装阶段我们使用了“透传模式”(把所有流量给 Swoole)。当你安装完成并准备正式运营时,必须切换回 “生产模式”。
生产模式优势:
- 性能提升:图片、JS、CSS 由 Nginx 直接处理,不再消耗 Swoole 的 CPU 资源。
- 安全加固:禁止直接访问
.env等敏感文件。 - 缓存优化:为静态资源添加浏览器缓存头。
操作步骤:
- 首先执行
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' PHP_8_0获取 PHP 容器 IP (例如172.18.0.4)。 - 在 1Panel 网站配置中,用下方代码完全覆盖原有配置。
Nginx
# =========================================================
# CRMEB Pro 3.5 生产环境配置 (1Panel 标准版)
# =========================================================
# 定义上游 Swoole 服务
# ⚠️ 必须修改 IP 为你的 PHP 容器真实 IP
upstream crmeb_swoole {
server 172.18.0.4:20199;
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;
# 日志路径 (1Panel 默认)
access_log /www/sites/1gv.cn/log/access.log main;
error_log /www/sites/1gv.cn/log/error.log;
# SSL 配置 (1Panel 默认,保持不变)
ssl_certificate /www/sites/1gv.cn/ssl/fullchain.pem;
ssl_certificate_key /www/sites/1gv.cn/ssl/privkey.pem;
ssl_protocols TLSv1.3 TLSv1.2;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK:!KRB5:!SRP:!CAMELLIA:!SEED;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";
# ================= 生产环境路由逻辑 =================
# 1. 静态资源加速 (Nginx 直接处理,不经过 Swoole)
# 包括图片、CSS、JS、字体文件
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2|woff|ttf|svg|eot)$ {
expires 7d; # 开启浏览器缓存 7 天
access_log off; # 关闭访问日志,节省磁盘空间
try_files $uri @swoole; # 兜底:如果文件不存在,才问 Swoole (处理动态生成的图片)
}
# 2. 上传目录单独处理
location ^~ /uploads/ {
expires 7d;
}
# 3. 禁止访问敏感文件 (安全加固)
location ~ /(\.env|\.git|\.htaccess|composer\.json|composer\.lock) {
deny all;
}
# 4. 核心业务转发 (所有其他请求 -> Swoole)
location / {
proxy_pass http://crmeb_swoole;
# 代理头设置
proxy_http_version 1.1;
proxy_read_timeout 360s;
proxy_redirect off;
# WebSocket 支持 (聊天系统必须)
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# 传递真实 IP
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;
add_header X-Cache $upstream_cache_status;
}
# 5. PHP 脚本转发 (兼容旧逻辑)
location ~* \.php$ {
proxy_pass http://crmeb_swoole;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 6. 定义 @swoole 命名位置 (作为兜底)
location @swoole {
proxy_pass http://crmeb_swoole;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# 404 页面
error_page 404 /404.html;
}
第五章:灾难恢复手册 (Panic Button)
在二次开发过程中,如果系统突然挂了,请按以下决策树进行自救。
场景 1:502 Bad Gateway
- 现象:浏览器显示 502。
- 原因:Swoole 进程挂了,或者 Nginx 连不上 Swoole。
- 自救指令:
supervisorctl status crmeb_pro(看进程是否活着)- 如果活着 -> 检查 Nginx 配置里的 IP 是否变了。
- 如果死了 (BACKOFF/EXITED) ->
dev-log(看报错)。
场景 2:修改代码不生效
- 现象:改了 PHP 逻辑,刷新页面还是旧的。
- 原因:OPCache 缓存或 Swoole 内存驻留。
- 自救指令:
dev-reload(轻量级重载) 或dev-restart(强制重启)。
场景 3:权限错误 (Permission Denied)
- 现象:上传图片失败,或日志显示无法写入。
- 原因:Docker 容器内的
www-data用户对宿主机挂载的目录没有写权限。 - 自救指令:Bash
# 简单粗暴给权限 (开发环境推荐) chmod -R 777 /www/sites/1gv.cn/index/public/uploads chmod -R 777 /www/sites/1gv.cn/index/runtime
📝 总结:为什么这次部署这么难?
这次部署之所以曲折,是因为你正好撞上了 三个维度的复杂性叠加:
- 架构复杂性:CRMEB Pro 使用 Swoole,而不是传统的 PHP-FPM。它是一个常驻内存的服务,这本身就比普通 PHP 网站难维护。
- 环境隔离性:1Panel 2.0 强制执行更严格的 Docker 网络隔离。以前在宝塔上
127.0.0.1随便连,现在必须理解 Docker Network。 - 配置敏感性:ThinkPHP 框架对配置文件格式的苛刻要求(不能有括号、注释),导致了最开始的启动失败。
现在的你,已经拥有了一套完整的、基于容器化的高性能开发环境。祝你的二次开发顺利!

