Upload 8 files
Browse files- DEPLOYMENT_GUIDE.md +318 -0
- Dockerfile +50 -226
- LICENSE +21 -0
- app.py +231 -31
- requirements.txt +25 -5
- start-services.sh +134 -0
DEPLOYMENT_GUIDE.md
ADDED
@@ -0,0 +1,318 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Hugging Face Spaces WordPress 部署指南
|
2 |
+
|
3 |
+
本指南将帮助您在 Hugging Face Spaces 上成功部署 WordPress 应用。
|
4 |
+
|
5 |
+
## 📋 部署前准备
|
6 |
+
|
7 |
+
### 1. 账户要求
|
8 |
+
- Hugging Face 账户(免费或付费)
|
9 |
+
- 基本的 Git 操作知识
|
10 |
+
|
11 |
+
### 2. 文件清单
|
12 |
+
确保您有以下文件:
|
13 |
+
|
14 |
+
```
|
15 |
+
├── Dockerfile # Docker 构建文件
|
16 |
+
├── app.py # Python 应用入口
|
17 |
+
├── requirements.txt # Python 依赖
|
18 |
+
├── wp-config.php # WordPress 配置
|
19 |
+
├── monitor-cleanup.sh # 清理脚本
|
20 |
+
├── start-services.sh # 服务启动脚本
|
21 |
+
├── test-deployment.sh # 部署测试脚本
|
22 |
+
├── .dockerignore # Docker 忽略文件
|
23 |
+
├── README_SPACES.md # Spaces 说明文档
|
24 |
+
└── DEPLOYMENT_GUIDE.md # 本部署指南
|
25 |
+
```
|
26 |
+
|
27 |
+
## 🚀 部署步骤
|
28 |
+
|
29 |
+
### 步骤 1: 创建 Hugging Face Space
|
30 |
+
|
31 |
+
1. 访问 [Hugging Face Spaces](https://huggingface.co/spaces)
|
32 |
+
2. 点击 **"Create new Space"**
|
33 |
+
3. 填写 Space 信息:
|
34 |
+
- **Space name**: 选择一个唯一的名称(如:`my-wordpress-site`)
|
35 |
+
- **License**: 选择合适的许可证
|
36 |
+
- **SDK**: 选择 **"Docker"**
|
37 |
+
- **Visibility**: 选择 Public 或 Private
|
38 |
+
4. 点击 **"Create Space"**
|
39 |
+
|
40 |
+
### 步骤 2: 克隆仓库
|
41 |
+
|
42 |
+
```bash
|
43 |
+
# 克隆您的 Space 仓库
|
44 |
+
git clone https://huggingface.co/spaces/YOUR_USERNAME/YOUR_SPACE_NAME
|
45 |
+
cd YOUR_SPACE_NAME
|
46 |
+
```
|
47 |
+
|
48 |
+
### 步骤 3: 上传文件
|
49 |
+
|
50 |
+
将所有必要文件复制到 Space 仓库目录:
|
51 |
+
|
52 |
+
```bash
|
53 |
+
# 复制所有文件到 Space 目录
|
54 |
+
cp /path/to/wordpress-files/* ./
|
55 |
+
|
56 |
+
# 检查文件
|
57 |
+
ls -la
|
58 |
+
```
|
59 |
+
|
60 |
+
### 步骤 4: 提交和推送
|
61 |
+
|
62 |
+
```bash
|
63 |
+
# 添加所有文件
|
64 |
+
git add .
|
65 |
+
|
66 |
+
# 提交更改
|
67 |
+
git commit -m "Initial WordPress deployment for Hugging Face Spaces"
|
68 |
+
|
69 |
+
# 推送到远程仓库
|
70 |
+
git push origin main
|
71 |
+
```
|
72 |
+
|
73 |
+
### 步骤 5: 等待构建
|
74 |
+
|
75 |
+
1. 返回您的 Space 页面
|
76 |
+
2. Hugging Face 会自动检测 Dockerfile 并开始构建
|
77 |
+
3. 构建过程通常需要 5-15 分钟
|
78 |
+
4. 您可以在 "Logs" 标签页查看构建进度
|
79 |
+
|
80 |
+
## 🔧 配置说明
|
81 |
+
|
82 |
+
### 环境变量(可选)
|
83 |
+
|
84 |
+
在 Space 设置中,您可以添加以下环境变量:
|
85 |
+
|
86 |
+
```bash
|
87 |
+
# WordPress 配置
|
88 |
+
WORDPRESS_DB_NAME=wordpress
|
89 |
+
WORDPRESS_DB_USER=wordpress
|
90 |
+
WORDPRESS_DB_PASSWORD=wordpress
|
91 |
+
|
92 |
+
# 清理配置
|
93 |
+
FILE_RETENTION_DAYS=365
|
94 |
+
AUTO_CLEANUP_ENABLED=true
|
95 |
+
|
96 |
+
# 调试模式(仅开发时使用)
|
97 |
+
WP_DEBUG=false
|
98 |
+
```
|
99 |
+
|
100 |
+
### 自定义配置
|
101 |
+
|
102 |
+
#### 修改文件保留期限
|
103 |
+
|
104 |
+
编辑 `wp-config.php`:
|
105 |
+
|
106 |
+
```php
|
107 |
+
// 修改保留天数(默认365天)
|
108 |
+
define('FILE_RETENTION_DAYS', 180); // 改为6个月
|
109 |
+
```
|
110 |
+
|
111 |
+
#### 禁用自动清理
|
112 |
+
|
113 |
+
编辑 `wp-config.php`:
|
114 |
+
|
115 |
+
```php
|
116 |
+
// 禁用自动清理
|
117 |
+
define('AUTO_CLEANUP_ENABLED', false);
|
118 |
+
```
|
119 |
+
|
120 |
+
#### 修改内存限制
|
121 |
+
|
122 |
+
编辑 `wp-config.php`:
|
123 |
+
|
124 |
+
```php
|
125 |
+
// 增加内存限制
|
126 |
+
ini_set('memory_limit', '512M');
|
127 |
+
```
|
128 |
+
|
129 |
+
## 🔍 验证部署
|
130 |
+
|
131 |
+
### 自动测试
|
132 |
+
|
133 |
+
部署完成后,您可以运行测试脚本:
|
134 |
+
|
135 |
+
```bash
|
136 |
+
# 在本地测试(如果您有访问权限)
|
137 |
+
bash test-deployment.sh
|
138 |
+
```
|
139 |
+
|
140 |
+
### 手动验证
|
141 |
+
|
142 |
+
访问以下URL验证部署:
|
143 |
+
|
144 |
+
1. **主页**: `https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/`
|
145 |
+
2. **WordPress**: `https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/wordpress`
|
146 |
+
3. **健康检查**: `https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/health`
|
147 |
+
4. **清理状态**: `https://YOUR_USERNAME-YOUR_SPACE_NAME.hf.space/api/cleanup/status`
|
148 |
+
|
149 |
+
### 检查清单
|
150 |
+
|
151 |
+
- [ ] 主页正常显示
|
152 |
+
- [ ] WordPress 安装页面可访问
|
153 |
+
- [ ] 健康检查 API 返回正常状态
|
154 |
+
- [ ] 清理状态 API 返回配置信息
|
155 |
+
- [ ] 可以创建 WordPress 管理员账户
|
156 |
+
- [ ] 可以登录 WordPress 后台
|
157 |
+
- [ ] 文件上传功能正常
|
158 |
+
- [ ] 清理统计在仪表板显示
|
159 |
+
|
160 |
+
## 🛠️ 故障排除
|
161 |
+
|
162 |
+
### 常见问题
|
163 |
+
|
164 |
+
#### 1. 构建失败
|
165 |
+
|
166 |
+
**症状**: Space 显示构建错误
|
167 |
+
|
168 |
+
**解决方案**:
|
169 |
+
- 检查 Dockerfile 语法
|
170 |
+
- 确保所有文件都已正确上传
|
171 |
+
- 查看构建日志中的具体错误信息
|
172 |
+
|
173 |
+
#### 2. 应用无法启动
|
174 |
+
|
175 |
+
**症状**: Space 显示 "Application Error"
|
176 |
+
|
177 |
+
**解决方案**:
|
178 |
+
- 检查 `start-services.sh` 脚本权限
|
179 |
+
- 确保端口 7860 正确配置
|
180 |
+
- 查看应用日志
|
181 |
+
|
182 |
+
#### 3. WordPress 数据库错误
|
183 |
+
|
184 |
+
**症状**: WordPress 显示数据库连接错误
|
185 |
+
|
186 |
+
**解决方案**:
|
187 |
+
- 检查 SQLite 插件是否正确安装
|
188 |
+
- 确认数据库目录权限
|
189 |
+
- 验证 `wp-config.php` 配置
|
190 |
+
|
191 |
+
#### 4. 文件上传失败
|
192 |
+
|
193 |
+
**症状**: 无法上传媒体文件
|
194 |
+
|
195 |
+
**解决方案**:
|
196 |
+
- 检查上传目录权限
|
197 |
+
- 确认磁盘空间充足
|
198 |
+
- 检查 PHP 上传限制
|
199 |
+
|
200 |
+
### 调试模式
|
201 |
+
|
202 |
+
启用调试模式以获取更多信息:
|
203 |
+
|
204 |
+
1. 编辑 `wp-config.php`:
|
205 |
+
```php
|
206 |
+
define('WP_DEBUG', true);
|
207 |
+
define('WP_DEBUG_DISPLAY', true);
|
208 |
+
```
|
209 |
+
|
210 |
+
2. 重新部署 Space
|
211 |
+
|
212 |
+
3. 查看错误信息
|
213 |
+
|
214 |
+
### 日志查看
|
215 |
+
|
216 |
+
如果您有容器访问权限,可以查看日志:
|
217 |
+
|
218 |
+
```bash
|
219 |
+
# WordPress 清理日志
|
220 |
+
tail -f /var/log/wordpress/cleanup.log
|
221 |
+
|
222 |
+
# Apache 错误日志
|
223 |
+
tail -f /var/log/apache2/error.log
|
224 |
+
|
225 |
+
# Python 应用日志
|
226 |
+
tail -f /var/log/python-app.log
|
227 |
+
```
|
228 |
+
|
229 |
+
## 📈 性能优化
|
230 |
+
|
231 |
+
### 1. 图片优化
|
232 |
+
|
233 |
+
- 上传前压缩图片
|
234 |
+
- 使用 WebP 格式
|
235 |
+
- 安装图片优化插件
|
236 |
+
|
237 |
+
### 2. 缓存配置
|
238 |
+
|
239 |
+
- 安装缓存插件(如 W3 Total Cache)
|
240 |
+
- 启用浏览器缓存
|
241 |
+
- 配置 CDN(如果需要)
|
242 |
+
|
243 |
+
### 3. 数据库优化
|
244 |
+
|
245 |
+
- 定期清理垃圾评论
|
246 |
+
- 限制文章修订版本
|
247 |
+
- 删除未使用的插件和主题
|
248 |
+
|
249 |
+
### 4. 监控和维护
|
250 |
+
|
251 |
+
- 定期检查清理日志
|
252 |
+
- 监控磁盘使用情况
|
253 |
+
- 保持 WordPress 和插件更新
|
254 |
+
|
255 |
+
## 🔒 安全建议
|
256 |
+
|
257 |
+
### 1. 强密码策略
|
258 |
+
|
259 |
+
- 使用复杂的管理员密码
|
260 |
+
- 启用双因素认证
|
261 |
+
- 定期更换密码
|
262 |
+
|
263 |
+
### 2. 插件安全
|
264 |
+
|
265 |
+
- 只安装必要的插件
|
266 |
+
- 保持插件更新
|
267 |
+
- 定期审查已安装插件
|
268 |
+
|
269 |
+
### 3. 访问控制
|
270 |
+
|
271 |
+
- 限制管理员账户数量
|
272 |
+
- 使用强用户名(避免 "admin")
|
273 |
+
- 配置 IP 白名单(如果需要)
|
274 |
+
|
275 |
+
### 4. 备份策略
|
276 |
+
|
277 |
+
- 定期导出重要内容
|
278 |
+
- 备份数据库文件
|
279 |
+
- 保存配置文件副本
|
280 |
+
|
281 |
+
## 📞 获取帮助
|
282 |
+
|
283 |
+
### 官方资源
|
284 |
+
|
285 |
+
- [Hugging Face Spaces 文档](https://huggingface.co/docs/hub/spaces)
|
286 |
+
- [WordPress 官方文档](https://wordpress.org/support/)
|
287 |
+
- [Docker 官方文档](https://docs.docker.com/)
|
288 |
+
|
289 |
+
### 社区支持
|
290 |
+
|
291 |
+
- Hugging Face 社区论坛
|
292 |
+
- WordPress 支持论坛
|
293 |
+
- GitHub Issues(如果项目开源)
|
294 |
+
|
295 |
+
### 技术支持
|
296 |
+
|
297 |
+
如果遇到技术问题,请提供以下信息:
|
298 |
+
|
299 |
+
1. Space 名称和 URL
|
300 |
+
2. 错误信息截图
|
301 |
+
3. 相关日志内容
|
302 |
+
4. 复现步骤
|
303 |
+
5. 环境配置信息
|
304 |
+
|
305 |
+
## 📄 许可证和免责声明
|
306 |
+
|
307 |
+
本部署方案基于开源软件构建,请遵守相关许可证条款:
|
308 |
+
|
309 |
+
- WordPress: GPL v2+
|
310 |
+
- Apache: Apache License 2.0
|
311 |
+
- Python: PSF License
|
312 |
+
- SQLite: Public Domain
|
313 |
+
|
314 |
+
**免责声明**: 本方案仅供学习和测试使用,生产环境使用前请进行充分测试和安全评估。
|
315 |
+
|
316 |
+
---
|
317 |
+
|
318 |
+
**祝您部署成功!** 🎉
|
Dockerfile
CHANGED
@@ -1,246 +1,70 @@
|
|
1 |
-
|
|
|
2 |
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
RUN apt-get update && apt-get install -y \
|
5 |
sqlite3 \
|
6 |
-
|
7 |
-
|
8 |
wget \
|
9 |
unzip \
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
&&
|
14 |
-
|
15 |
-
# 下载并安装WordPress核心文件
|
16 |
-
RUN cd /tmp && \
|
17 |
-
wget --timeout=30 --tries=3 https://wordpress.org/latest.tar.gz && \
|
18 |
-
tar -xzf latest.tar.gz && \
|
19 |
-
cp -r wordpress/* /var/www/html/ && \
|
20 |
-
rm -rf wordpress latest.tar.gz
|
21 |
|
22 |
# 下载并安装SQLite Integration插件
|
23 |
RUN cd /tmp && \
|
24 |
-
wget
|
25 |
-
unzip sqlite-integration.zip && \
|
26 |
-
mv sqlite-integration /
|
27 |
-
rm sqlite-integration.zip
|
28 |
-
|
29 |
-
# 复制PHP配置
|
30 |
-
COPY config/wp_php.ini /usr/local/etc/php/conf.d/conf.ini
|
31 |
-
|
32 |
-
# 创建SQLite数据库目录
|
33 |
-
RUN mkdir -p /var/www/html/wp-content/database
|
34 |
-
|
35 |
-
# 配置Apache监听7860端口
|
36 |
-
RUN sed -i 's/Listen 80/Listen 7860/' /etc/apache2/ports.conf && \
|
37 |
-
sed -i 's/:80>/:7860>/' /etc/apache2/sites-available/000-default.conf
|
38 |
|
39 |
# 创建必要的目录
|
40 |
-
RUN mkdir -p /var/www/html/wp-content/
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
# 创建SQLite数据库配置文件
|
45 |
-
RUN echo "<?php\n\
|
46 |
-
define('USE_MYSQL', false);\n\
|
47 |
-
define('DB_DIR', '/var/www/html/wp-content/database/');\n\
|
48 |
-
define('DB_FILE', 'wordpress.db');\n" > /var/www/html/wp-content/db.php
|
49 |
-
|
50 |
-
# 创建SQLite Integration必须使用插件加载器
|
51 |
-
RUN echo "<?php\n\
|
52 |
-
// SQLite Integration Must Use Plugin Loader\n\
|
53 |
-
if ( ! defined( 'ABSPATH' ) ) {\n\
|
54 |
-
exit;\n\
|
55 |
-
}\n\
|
56 |
-
\n\
|
57 |
-
// 加载SQLite Integration插件\n\
|
58 |
-
if ( file_exists( WP_CONTENT_DIR . '/plugins/sqlite-integration/load.php' ) ) {\n\
|
59 |
-
require_once WP_CONTENT_DIR . '/plugins/sqlite-integration/load.php';\n\
|
60 |
-
}\n" > /var/www/html/wp-content/mu-plugins/sqlite-integration-loader.php
|
61 |
-
|
62 |
-
# 创建wp-config.php用于SQLite
|
63 |
-
RUN echo "<?php\n\
|
64 |
-
define('DB_NAME', 'wordpress');\n\
|
65 |
-
define('DB_USER', 'root');\n\
|
66 |
-
define('DB_PASSWORD', '');\n\
|
67 |
-
define('DB_HOST', '');\n\
|
68 |
-
define('DB_CHARSET', 'utf8');\n\
|
69 |
-
define('DB_COLLATE', '');\n\
|
70 |
-
define('FS_METHOD', 'direct');\n\
|
71 |
-
define('WP_DEBUG', false);\n\
|
72 |
-
define('SQLITE_INTEGRATION_PLUGIN_PATH', '/var/www/html/wp-content/plugins/sqlite-integration/');\n\
|
73 |
-
\$table_prefix = 'wp_';\n\
|
74 |
-
if ( ! defined( 'ABSPATH' ) ) {\n\
|
75 |
-
define( 'ABSPATH', __DIR__ . '/' );\n\
|
76 |
-
}\n\
|
77 |
-
require_once ABSPATH . 'wp-settings.php';\n" > /var/www/html/wp-config.php
|
78 |
|
79 |
-
#
|
80 |
-
|
81 |
-
|
82 |
-
\n\
|
83 |
-
echo "=== WordPress GitHub Backup Loader ==="\n\
|
84 |
-
\n\
|
85 |
-
# 检查环境变量\n\
|
86 |
-
if [ -z "$GITHUB_TOKEN" ] || [ -z "$GITHUB_REPO" ]; then\n\
|
87 |
-
echo "警告: GITHUB_TOKEN 或 GITHUB_REPO 环境变量未设置,跳过GitHub备份加载"\n\
|
88 |
-
else\n\
|
89 |
-
echo "开始从GitHub加载备份数据..."\n\
|
90 |
-
\n\
|
91 |
-
# 设置GitHub API URL\n\
|
92 |
-
GITHUB_API="https://api.github.com/repos/$GITHUB_REPO"\n\
|
93 |
-
\n\
|
94 |
-
# 获取最近30天的备份文件
|
95 |
-
THIRTY_DAYS_AGO=\$\(date -d \"30 days ago\" +%Y-%m-%d\)\n\
|
96 |
-
\n\
|
97 |
-
echo "查找 $THIRTY_DAYS_AGO 之后的备份文件..."\n\
|
98 |
-
\n\
|
99 |
-
# 获取备份文件列表
|
100 |
-
BACKUP_RESPONSE=\$\(curl -s -H \"Authorization: token \$GITHUB_TOKEN\" \"\$GITHUB_API/contents/backups\"\)\n\
|
101 |
-
\n\
|
102 |
-
# 检查API响应是否有效\n\
|
103 |
-
if echo \"\$BACKUP_RESPONSE\" | jq -e . >/dev/null 2>&1; then\n\
|
104 |
-
# 检查是否是数组\n\
|
105 |
-
if echo \"\$BACKUP_RESPONSE\" | jq -e 'type == \"array\"' >/dev/null 2>&1; then\n\
|
106 |
-
BACKUP_FILES=\$\(echo \"\$BACKUP_RESPONSE\" | jq -r \".[] | select(.name | test(\\\"backup-[0-9]{4}-[0-9]{2}-[0-9]{2}\\\")) | .name\" | sort -r\)\n\
|
107 |
-
else\n\
|
108 |
-
echo \"GitHub API返回错误: \$\(echo \"\$BACKUP_RESPONSE\" | jq -r '.message // \"未知错误\"'\)\"\n\
|
109 |
-
BACKUP_FILES=\"\"\n\
|
110 |
-
fi\n\
|
111 |
-
else\n\
|
112 |
-
echo \"GitHub API响应格式错误\"\n\
|
113 |
-
BACKUP_FILES=\"\"\n\
|
114 |
-
fi\n\
|
115 |
-
\n\
|
116 |
-
if [ -z \"\$BACKUP_FILES\" ]; then\n\
|
117 |
-
echo \"��找到备份文件\"\n\
|
118 |
-
else\n\
|
119 |
-
# 获取最新的备份文件\n\
|
120 |
-
LATEST_BACKUP=\$\(echo \"\$BACKUP_FILES\" | head -n 1\)\n\
|
121 |
-
echo \"找到最新备份: \$LATEST_BACKUP\"\n\
|
122 |
-
\n\
|
123 |
-
# 下载并解压备份\n\
|
124 |
-
DOWNLOAD_URL=\$\(curl -s -H \"Authorization: token \$GITHUB_TOKEN\" \\\n\ \"\$GITHUB_API/contents/backups/\$LATEST_BACKUP\" | jq -r \".download_url\"\)\n\
|
125 |
-
\n\
|
126 |
-
if [ \"\$DOWNLOAD_URL\" != \"null\" ]; then\n\
|
127 |
-
echo \"下载备份文件...\"\n\
|
128 |
-
cd /var/www/html/wp-content/backup\n\
|
129 |
-
curl -L -o \"\$LATEST_BACKUP\" \"\$DOWNLOAD_URL\"\n\
|
130 |
-
\n\
|
131 |
-
# 解压备份\n\
|
132 |
-
if [[ \"\$LATEST_BACKUP\" == *.tar.gz ]]; then\n\
|
133 |
-
echo \"解压备份文件...\"\n\
|
134 |
-
tar -xzf \"\$LATEST_BACKUP\"\n\
|
135 |
-
\n\
|
136 |
-
# 恢复数据库\n\
|
137 |
-
if [ -f \"wordpress.db\" ]; then\n\
|
138 |
-
echo \"恢复SQLite数据库...\"\n\
|
139 |
-
cp wordpress.db /var/www/html/wp-content/database/\n\
|
140 |
-
fi\n\
|
141 |
-
\n\
|
142 |
-
# 恢复上传文件\n\
|
143 |
-
if [ -d \"uploads\" ]; then\n\
|
144 |
-
echo \"恢复上传文件...\"\n\
|
145 |
-
cp -r uploads/* /var/www/html/wp-content/uploads/\n\
|
146 |
-
fi\n\
|
147 |
-
\n\
|
148 |
-
echo \"备份恢复完成\"\n\
|
149 |
-
fi\n\
|
150 |
-
fi\n\
|
151 |
-
fi\n\
|
152 |
-
fi\n\
|
153 |
-
\n\
|
154 |
-
echo "=== 启动Apache ===\n"\
|
155 |
-
# 设置权限 (跳过chown,在HF Spaces中不需要)\n\
|
156 |
-
chmod -R 755 /var/www/html 2>/dev/null || true\n\
|
157 |
-
\n\
|
158 |
-
# 启动Apache\n\
|
159 |
-
exec apache2-foreground' > /usr/local/bin/start-wordpress.sh && \
|
160 |
-
chmod +x /usr/local/bin/start-wordpress.sh
|
161 |
|
162 |
-
#
|
163 |
-
RUN
|
164 |
-
set -e\n\
|
165 |
-
\n\
|
166 |
-
echo "=== WordPress GitHub Backup ==="\n\
|
167 |
-
\n\
|
168 |
-
# 检查环境变量\n\
|
169 |
-
if [ -z "$GITHUB_TOKEN" ] || [ -z "$GITHUB_REPO" ]; then\n\
|
170 |
-
echo "错误: GITHUB_TOKEN 或 GITHUB_REPO 环境变量未设置"\n\
|
171 |
-
exit 1\n\
|
172 |
-
fi\n\
|
173 |
-
\n\
|
174 |
-
# 创建备份目录\n\
|
175 |
-
BACKUP_DIR="/tmp/wordpress-backup"\n\
|
176 |
-
DATE=$(date +%Y-%m-%d-%H%M%S)\n\
|
177 |
-
BACKUP_NAME="backup-$DATE"\n\
|
178 |
-
\n\
|
179 |
-
mkdir -p "$BACKUP_DIR/$BACKUP_NAME"\n\
|
180 |
-
\n\
|
181 |
-
echo "创建备份: $BACKUP_NAME"\n\
|
182 |
-
\n\
|
183 |
-
# 备份SQLite数据库\n\
|
184 |
-
if [ -f "/var/www/html/wp-content/database/wordpress.db" ]; then\n\
|
185 |
-
echo "备份SQLite数据库..."\n\
|
186 |
-
cp /var/www/html/wp-content/database/wordpress.db "$BACKUP_DIR/$BACKUP_NAME/"\n\
|
187 |
-
fi\n\
|
188 |
-
\n\
|
189 |
-
# 备份上传文件\n\
|
190 |
-
if [ -d "/var/www/html/wp-content/uploads" ]; then\n\
|
191 |
-
echo "备份上传文件..."\n\
|
192 |
-
cp -r /var/www/html/wp-content/uploads "$BACKUP_DIR/$BACKUP_NAME/"\n\
|
193 |
-
fi\n\
|
194 |
-
\n\
|
195 |
-
# 创建压缩包\n\
|
196 |
-
cd "$BACKUP_DIR"\n\
|
197 |
-
tar -czf "$BACKUP_NAME.tar.gz" "$BACKUP_NAME"\n\
|
198 |
-
\n\
|
199 |
-
# 上传到GitHub\n\
|
200 |
-
echo "上传备份到GitHub..."\n\
|
201 |
-
\n\
|
202 |
-
# 将文件转换为base64\n\
|
203 |
-
FILE_CONTENT=$(base64 -w 0 "$BACKUP_NAME.tar.gz")\n\
|
204 |
-
\n\
|
205 |
-
# 上传到GitHub\n\
|
206 |
-
curl -X PUT \\\n\
|
207 |
-
-H "Authorization: token $GITHUB_TOKEN" \\\n\
|
208 |
-
-H "Content-Type: application/json" \\\n\
|
209 |
-
-d "{\\\"message\\\": \\\"WordPress backup $DATE\\\", \\\"content\\\": \\\"$FILE_CONTENT\\\"}" \\\n\
|
210 |
-
"https://api.github.com/repos/$GITHUB_REPO/contents/backups/$BACKUP_NAME.tar.gz"\n\
|
211 |
-
\n\
|
212 |
-
echo "备份完成: $BACKUP_NAME.tar.gz"\n\
|
213 |
-
\n\
|
214 |
-
# 清理临时文件\n\
|
215 |
-
rm -rf "$BACKUP_DIR"\n\
|
216 |
-
\n\
|
217 |
-
echo "备份上传到GitHub完成"' > /usr/local/bin/backup-wordpress.sh && \
|
218 |
-
chmod +x /usr/local/bin/backup-wordpress.sh
|
219 |
|
220 |
-
#
|
|
|
221 |
|
222 |
-
#
|
223 |
-
|
224 |
-
|
225 |
-
chmod 644 /var/log/php_errors.log
|
226 |
|
227 |
-
#
|
228 |
-
|
229 |
-
|
230 |
-
a2enmod expires
|
231 |
|
232 |
-
# 设置
|
233 |
-
RUN echo "
|
234 |
|
235 |
-
#
|
236 |
-
|
237 |
|
238 |
-
#
|
239 |
-
|
240 |
-
|
241 |
|
242 |
-
#
|
243 |
-
|
244 |
|
245 |
-
#
|
246 |
-
CMD ["/
|
|
|
1 |
+
# Hugging Face Spaces WordPress Dockerfile
|
2 |
+
# 适配单容器部署,使用SQLite数据库,包含自动清理功能
|
3 |
|
4 |
+
FROM wordpress:6.4-apache
|
5 |
+
|
6 |
+
# 设置环境变量
|
7 |
+
ENV DEBIAN_FRONTEND=noninteractive
|
8 |
+
ENV WORDPRESS_DB_HOST=localhost
|
9 |
+
ENV WORDPRESS_DB_NAME=wordpress
|
10 |
+
ENV WORDPRESS_DB_USER=wordpress
|
11 |
+
ENV WORDPRESS_DB_PASSWORD=wordpress
|
12 |
+
ENV PYTHONUNBUFFERED=1
|
13 |
+
|
14 |
+
# 安装必要的包
|
15 |
RUN apt-get update && apt-get install -y \
|
16 |
sqlite3 \
|
17 |
+
php-sqlite3 \
|
18 |
+
cron \
|
19 |
wget \
|
20 |
unzip \
|
21 |
+
python3 \
|
22 |
+
python3-pip \
|
23 |
+
curl \
|
24 |
+
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
# 下载并安装SQLite Integration插件
|
27 |
RUN cd /tmp && \
|
28 |
+
wget https://downloads.wordpress.org/plugin/sqlite-database-integration.2.1.5.zip && \
|
29 |
+
unzip sqlite-database-integration.2.1.5.zip && \
|
30 |
+
mv sqlite-database-integration /usr/src/wordpress/wp-content/plugins/ && \
|
31 |
+
rm sqlite-database-integration.2.1.5.zip
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
# 创建必要的目录
|
34 |
+
RUN mkdir -p /var/www/html/wp-content/database \
|
35 |
+
&& mkdir -p /var/log/wordpress \
|
36 |
+
&& mkdir -p /scripts
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
+
# 复制Python应用文件
|
39 |
+
COPY app.py /app/
|
40 |
+
COPY requirements.txt /app/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
|
42 |
+
# 安装Python依赖
|
43 |
+
RUN pip3 install --no-cache-dir -r /app/requirements.txt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
|
45 |
+
# 复制自定义wp-config.php
|
46 |
+
COPY wp-config.php /usr/src/wordpress/
|
47 |
|
48 |
+
# 复制监控清理脚本
|
49 |
+
COPY monitor-cleanup.sh /scripts/
|
50 |
+
RUN chmod +x /scripts/monitor-cleanup.sh
|
|
|
51 |
|
52 |
+
# 复制启动脚本
|
53 |
+
COPY start-services.sh /scripts/
|
54 |
+
RUN chmod +x /scripts/start-services.sh
|
|
|
55 |
|
56 |
+
# 设置cron任务 - 每天凌晨2点执行清理
|
57 |
+
RUN echo "0 2 * * * /scripts/monitor-cleanup.sh >> /var/log/wordpress/cleanup.log 2>&1" | crontab -
|
58 |
|
59 |
+
# 暴露端口7860 (Hugging Face Spaces标准端口)
|
60 |
+
EXPOSE 7860
|
61 |
|
62 |
+
# 修改Apache配置以使用端口7860
|
63 |
+
RUN sed -i 's/Listen 80/Listen 7860/' /etc/apache2/ports.conf && \
|
64 |
+
sed -i 's/:80>/:7860>/' /etc/apache2/sites-available/000-default.conf
|
65 |
|
66 |
+
# 设置工作目录
|
67 |
+
WORKDIR /var/www/html
|
68 |
|
69 |
+
# 启动命令
|
70 |
+
CMD ["/scripts/start-services.sh"]
|
LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
The MIT License (MIT)
|
2 |
+
|
3 |
+
Copyright (c) 2018 nezhar
|
4 |
+
|
5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6 |
+
of this software and associated documentation files (the "Software"), to deal
|
7 |
+
in the Software without restriction, including without limitation the rights
|
8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9 |
+
copies of the Software, and to permit persons to whom the Software is
|
10 |
+
furnished to do so, subject to the following conditions:
|
11 |
+
|
12 |
+
The above copyright notice and this permission notice shall be included in all
|
13 |
+
copies or substantial portions of the Software.
|
14 |
+
|
15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21 |
+
SOFTWARE.
|
app.py
CHANGED
@@ -1,38 +1,238 @@
|
|
1 |
#!/usr/bin/env python3
|
2 |
"""
|
3 |
-
Hugging Face
|
4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
"""
|
6 |
|
7 |
import os
|
8 |
-
import subprocess
|
9 |
import time
|
10 |
-
import
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
try:
|
25 |
-
while True:
|
26 |
-
time.sleep(60)
|
27 |
-
# Optional: Add health check here
|
28 |
-
print("💓 WordPress container is running...")
|
29 |
-
except KeyboardInterrupt:
|
30 |
-
print("\n🛑 Shutting down WordPress...")
|
31 |
-
sys.exit(0)
|
32 |
-
else:
|
33 |
-
print("❌ This should run inside a Docker container")
|
34 |
-
print("Please deploy this to Hugging Face Spaces with Docker SDK")
|
35 |
-
sys.exit(1)
|
36 |
-
|
37 |
-
if __name__ == "__main__":
|
38 |
-
main()
|
|
|
1 |
#!/usr/bin/env python3
|
2 |
"""
|
3 |
+
Hugging Face Spaces WordPress 应用入口文件
|
4 |
+
|
5 |
+
这个文件是 Hugging Face Spaces 的标准入口点,
|
6 |
+
但实际的 WordPress 应用运行在 Docker 容器中。
|
7 |
+
|
8 |
+
该文件主要用于:
|
9 |
+
1. 提供应用信息
|
10 |
+
2. 健康检查
|
11 |
+
3. 重定向到 WordPress
|
12 |
"""
|
13 |
|
14 |
import os
|
|
|
15 |
import time
|
16 |
+
import subprocess
|
17 |
+
from flask import Flask, redirect, jsonify, render_template_string
|
18 |
+
|
19 |
+
app = Flask(__name__)
|
20 |
+
|
21 |
+
# 应用信息
|
22 |
+
APP_INFO = {
|
23 |
+
"name": "WordPress for Hugging Face Spaces",
|
24 |
+
"version": "1.0.0",
|
25 |
+
"description": "WordPress 单容器部署,使用 SQLite 数据库,包含自动清理功能",
|
26 |
+
"author": "Hugging Face Spaces WordPress Team",
|
27 |
+
"wordpress_url": "http://localhost:7860"
|
28 |
+
}
|
29 |
+
|
30 |
+
# HTML 模板
|
31 |
+
INDEX_TEMPLATE = """
|
32 |
+
<!DOCTYPE html>
|
33 |
+
<html lang="zh-CN">
|
34 |
+
<head>
|
35 |
+
<meta charset="UTF-8">
|
36 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
37 |
+
<title>{{ app_info.name }}</title>
|
38 |
+
<style>
|
39 |
+
body {
|
40 |
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
41 |
+
margin: 0;
|
42 |
+
padding: 20px;
|
43 |
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
44 |
+
min-height: 100vh;
|
45 |
+
display: flex;
|
46 |
+
align-items: center;
|
47 |
+
justify-content: center;
|
48 |
+
}
|
49 |
+
.container {
|
50 |
+
background: white;
|
51 |
+
border-radius: 10px;
|
52 |
+
padding: 40px;
|
53 |
+
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
|
54 |
+
text-align: center;
|
55 |
+
max-width: 600px;
|
56 |
+
}
|
57 |
+
h1 {
|
58 |
+
color: #333;
|
59 |
+
margin-bottom: 10px;
|
60 |
+
}
|
61 |
+
.version {
|
62 |
+
color: #666;
|
63 |
+
font-size: 14px;
|
64 |
+
margin-bottom: 20px;
|
65 |
+
}
|
66 |
+
.description {
|
67 |
+
color: #555;
|
68 |
+
line-height: 1.6;
|
69 |
+
margin-bottom: 30px;
|
70 |
+
}
|
71 |
+
.btn {
|
72 |
+
display: inline-block;
|
73 |
+
background: #667eea;
|
74 |
+
color: white;
|
75 |
+
padding: 12px 30px;
|
76 |
+
text-decoration: none;
|
77 |
+
border-radius: 5px;
|
78 |
+
font-weight: bold;
|
79 |
+
transition: background 0.3s;
|
80 |
+
margin: 10px;
|
81 |
+
}
|
82 |
+
.btn:hover {
|
83 |
+
background: #5a6fd8;
|
84 |
+
}
|
85 |
+
.status {
|
86 |
+
margin-top: 30px;
|
87 |
+
padding: 15px;
|
88 |
+
background: #f8f9fa;
|
89 |
+
border-radius: 5px;
|
90 |
+
border-left: 4px solid #28a745;
|
91 |
+
}
|
92 |
+
.features {
|
93 |
+
text-align: left;
|
94 |
+
margin: 20px 0;
|
95 |
+
}
|
96 |
+
.features ul {
|
97 |
+
list-style-type: none;
|
98 |
+
padding: 0;
|
99 |
+
}
|
100 |
+
.features li {
|
101 |
+
padding: 5px 0;
|
102 |
+
position: relative;
|
103 |
+
padding-left: 20px;
|
104 |
+
}
|
105 |
+
.features li:before {
|
106 |
+
content: "✓";
|
107 |
+
position: absolute;
|
108 |
+
left: 0;
|
109 |
+
color: #28a745;
|
110 |
+
font-weight: bold;
|
111 |
+
}
|
112 |
+
</style>
|
113 |
+
</head>
|
114 |
+
<body>
|
115 |
+
<div class="container">
|
116 |
+
<h1>{{ app_info.name }}</h1>
|
117 |
+
<div class="version">版本 {{ app_info.version }}</div>
|
118 |
+
<div class="description">{{ app_info.description }}</div>
|
119 |
+
|
120 |
+
<div class="features">
|
121 |
+
<h3>主要特性:</h3>
|
122 |
+
<ul>
|
123 |
+
<li>单容器 Docker 部署</li>
|
124 |
+
<li>SQLite 轻量级数据库</li>
|
125 |
+
<li>自动文件清理 (保留1年)</li>
|
126 |
+
<li>性能优化配置</li>
|
127 |
+
<li>安全防护机制</li>
|
128 |
+
<li>实时监控面板</li>
|
129 |
+
</ul>
|
130 |
+
</div>
|
131 |
+
|
132 |
+
<a href="/wordpress" class="btn">进入 WordPress</a>
|
133 |
+
<a href="/health" class="btn">系统状态</a>
|
134 |
+
|
135 |
+
<div class="status">
|
136 |
+
<strong>状态:</strong> WordPress 正在运行中...<br>
|
137 |
+
<small>如果这是首次访问,WordPress 可能需要几分钟来初始化</small>
|
138 |
+
</div>
|
139 |
+
</div>
|
140 |
+
</body>
|
141 |
+
</html>
|
142 |
+
"""
|
143 |
+
|
144 |
+
@app.route('/')
|
145 |
+
def index():
|
146 |
+
"""主页 - 显示应用信息"""
|
147 |
+
return render_template_string(INDEX_TEMPLATE, app_info=APP_INFO)
|
148 |
+
|
149 |
+
@app.route('/wordpress')
|
150 |
+
def wordpress():
|
151 |
+
"""重定向到 WordPress"""
|
152 |
+
return redirect('http://localhost:7860', code=302)
|
153 |
+
|
154 |
+
@app.route('/health')
|
155 |
+
def health():
|
156 |
+
"""健康检查端点"""
|
157 |
+
try:
|
158 |
+
# 检查 WordPress 容器是否运行
|
159 |
+
result = subprocess.run(
|
160 |
+
['curl', '-f', '-s', 'http://localhost:7860'],
|
161 |
+
capture_output=True,
|
162 |
+
timeout=5
|
163 |
+
)
|
164 |
+
|
165 |
+
wordpress_status = "running" if result.returncode == 0 else "stopped"
|
166 |
+
|
167 |
+
# 获取系统信息
|
168 |
+
disk_usage = subprocess.run(
|
169 |
+
['df', '-h', '/'],
|
170 |
+
capture_output=True,
|
171 |
+
text=True
|
172 |
+
).stdout.split('\n')[1].split()[4] if subprocess.run(['df', '-h', '/'], capture_output=True).returncode == 0 else "unknown"
|
173 |
+
|
174 |
+
return jsonify({
|
175 |
+
"status": "healthy",
|
176 |
+
"timestamp": time.time(),
|
177 |
+
"services": {
|
178 |
+
"wordpress": wordpress_status,
|
179 |
+
"database": "sqlite",
|
180 |
+
"cleanup": "enabled"
|
181 |
+
},
|
182 |
+
"system": {
|
183 |
+
"disk_usage": disk_usage,
|
184 |
+
"uptime": time.time()
|
185 |
+
},
|
186 |
+
"app_info": APP_INFO
|
187 |
+
})
|
188 |
+
except Exception as e:
|
189 |
+
return jsonify({
|
190 |
+
"status": "error",
|
191 |
+
"error": str(e),
|
192 |
+
"timestamp": time.time()
|
193 |
+
}), 500
|
194 |
+
|
195 |
+
@app.route('/api/info')
|
196 |
+
def api_info():
|
197 |
+
"""API 信息端点"""
|
198 |
+
return jsonify(APP_INFO)
|
199 |
+
|
200 |
+
@app.route('/api/cleanup/status')
|
201 |
+
def cleanup_status():
|
202 |
+
"""清理状态 API"""
|
203 |
+
try:
|
204 |
+
# 读取清理日志
|
205 |
+
log_file = '/var/log/wordpress/cleanup.log'
|
206 |
+
if os.path.exists(log_file):
|
207 |
+
with open(log_file, 'r') as f:
|
208 |
+
lines = f.readlines()
|
209 |
+
recent_logs = lines[-10:] if len(lines) > 10 else lines
|
210 |
+
else:
|
211 |
+
recent_logs = ["暂无清理记录"]
|
212 |
+
|
213 |
+
return jsonify({
|
214 |
+
"status": "success",
|
215 |
+
"cleanup_enabled": True,
|
216 |
+
"retention_days": 365,
|
217 |
+
"recent_logs": [line.strip() for line in recent_logs],
|
218 |
+
"log_file": log_file
|
219 |
+
})
|
220 |
+
except Exception as e:
|
221 |
+
return jsonify({
|
222 |
+
"status": "error",
|
223 |
+
"error": str(e)
|
224 |
+
}), 500
|
225 |
+
|
226 |
+
if __name__ == '__main__':
|
227 |
+
# 在 Hugging Face Spaces 中,应用应该监听端口 7860
|
228 |
+
port = int(os.environ.get('PORT', 7860))
|
229 |
+
|
230 |
+
print(f"启动 {APP_INFO['name']} v{APP_INFO['version']}")
|
231 |
+
print(f"监听端口: {port}")
|
232 |
+
print(f"WordPress URL: {APP_INFO['wordpress_url']}")
|
233 |
|
234 |
+
app.run(
|
235 |
+
host='0.0.0.0',
|
236 |
+
port=port,
|
237 |
+
debug=False
|
238 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
@@ -1,6 +1,26 @@
|
|
1 |
-
#
|
2 |
-
# This WordPress deployment primarily uses Docker,
|
3 |
-
# but this file is included for HF Space compatibility
|
4 |
|
5 |
-
#
|
6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Python dependencies for Hugging Face Spaces WordPress app
|
|
|
|
|
2 |
|
3 |
+
# Web framework
|
4 |
+
Flask==2.3.3
|
5 |
+
Werkzeug==2.3.7
|
6 |
+
|
7 |
+
# HTTP requests
|
8 |
+
requests==2.31.0
|
9 |
+
|
10 |
+
# System utilities
|
11 |
+
psutil==5.9.5
|
12 |
+
|
13 |
+
# JSON handling
|
14 |
+
jsonschema==4.19.1
|
15 |
+
|
16 |
+
# Date and time utilities
|
17 |
+
python-dateutil==2.8.2
|
18 |
+
|
19 |
+
# Environment variables
|
20 |
+
python-dotenv==1.0.0
|
21 |
+
|
22 |
+
# Logging
|
23 |
+
coloredlogs==15.0.1
|
24 |
+
|
25 |
+
# Security
|
26 |
+
cryptography==41.0.4
|
start-services.sh
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
# Hugging Face Spaces WordPress 服务启动脚本
|
4 |
+
# 管理 WordPress、Python 应用和清理服务
|
5 |
+
|
6 |
+
set -e
|
7 |
+
|
8 |
+
echo "=== 启动 WordPress for Hugging Face Spaces ==="
|
9 |
+
|
10 |
+
# 创建必要的目录
|
11 |
+
echo "创建必要的目录..."
|
12 |
+
mkdir -p /var/www/html/wp-content/database
|
13 |
+
mkdir -p /var/www/html/wp-content/uploads
|
14 |
+
mkdir -p /var/www/html/wp-content/cache
|
15 |
+
mkdir -p /var/log/wordpress
|
16 |
+
mkdir -p /var/log/apache2
|
17 |
+
|
18 |
+
# 设置权限
|
19 |
+
echo "设置文件权限..."
|
20 |
+
chown -R www-data:www-data /var/www/html
|
21 |
+
chmod -R 755 /var/www/html
|
22 |
+
chown -R www-data:www-data /var/www/html/wp-content/database
|
23 |
+
chmod -R 755 /var/www/html/wp-content/database
|
24 |
+
|
25 |
+
# 检查并安装 SQLite 插件
|
26 |
+
echo "检查 SQLite 插件..."
|
27 |
+
if [ ! -d "/var/www/html/wp-content/plugins/sqlite-database-integration" ]; then
|
28 |
+
echo "安装 SQLite 数据库集成插件..."
|
29 |
+
cd /tmp
|
30 |
+
wget -q https://downloads.wordpress.org/plugin/sqlite-database-integration.2.1.5.zip
|
31 |
+
unzip -q sqlite-database-integration.2.1.5.zip
|
32 |
+
mv sqlite-database-integration /var/www/html/wp-content/plugins/
|
33 |
+
chown -R www-data:www-data /var/www/html/wp-content/plugins/sqlite-database-integration
|
34 |
+
rm sqlite-database-integration.2.1.5.zip
|
35 |
+
echo "SQLite 插件安装完成"
|
36 |
+
else
|
37 |
+
echo "SQLite 插件已存在"
|
38 |
+
fi
|
39 |
+
|
40 |
+
# 复制 wp-config.php 如果不存在
|
41 |
+
if [ ! -f "/var/www/html/wp-config.php" ]; then
|
42 |
+
echo "复制 wp-config.php..."
|
43 |
+
cp /usr/src/wordpress/wp-config.php /var/www/html/
|
44 |
+
chown www-data:www-data /var/www/html/wp-config.php
|
45 |
+
fi
|
46 |
+
|
47 |
+
# 启动 cron 服务
|
48 |
+
echo "启动 cron 服务..."
|
49 |
+
service cron start
|
50 |
+
|
51 |
+
# 启动 Apache 在后台
|
52 |
+
echo "启动 Apache 服务..."
|
53 |
+
apache2ctl start
|
54 |
+
|
55 |
+
# 等待 Apache 启动
|
56 |
+
sleep 3
|
57 |
+
|
58 |
+
# 检查 Apache 状态
|
59 |
+
if pgrep apache2 > /dev/null; then
|
60 |
+
echo "Apache 启动成功"
|
61 |
+
else
|
62 |
+
echo "Apache 启动失败"
|
63 |
+
exit 1
|
64 |
+
fi
|
65 |
+
|
66 |
+
# 启动 Python 应用
|
67 |
+
echo "启动 Python 应用..."
|
68 |
+
cd /app
|
69 |
+
export FLASK_ENV=production
|
70 |
+
export FLASK_APP=app.py
|
71 |
+
|
72 |
+
# 在后台启动 Python 应用
|
73 |
+
python3 app.py &
|
74 |
+
PYTHON_PID=$!
|
75 |
+
|
76 |
+
echo "Python 应用启动,PID: $PYTHON_PID"
|
77 |
+
|
78 |
+
# 等待服务启动
|
79 |
+
sleep 5
|
80 |
+
|
81 |
+
# 健康检查
|
82 |
+
echo "执行健康检查..."
|
83 |
+
for i in {1..10}; do
|
84 |
+
if curl -f -s http://localhost:7860/health > /dev/null; then
|
85 |
+
echo "健康检查通过"
|
86 |
+
break
|
87 |
+
else
|
88 |
+
echo "等待服务启动... ($i/10)"
|
89 |
+
sleep 2
|
90 |
+
fi
|
91 |
+
|
92 |
+
if [ $i -eq 10 ]; then
|
93 |
+
echo "健康检查失败,服务可能未正常启动"
|
94 |
+
fi
|
95 |
+
done
|
96 |
+
|
97 |
+
# 显示服务状态
|
98 |
+
echo "=== 服务状态 ==="
|
99 |
+
echo "Apache: $(pgrep apache2 > /dev/null && echo '运行中' || echo '已停止')"
|
100 |
+
echo "Python App: $(kill -0 $PYTHON_PID 2>/dev/null && echo '运行中' || echo '已停止')"
|
101 |
+
echo "Cron: $(pgrep cron > /dev/null && echo '运行中' || echo '已停止')"
|
102 |
+
|
103 |
+
# 显示访问信息
|
104 |
+
echo "=== 访问信息 ==="
|
105 |
+
echo "WordPress: http://localhost:7860/wordpress"
|
106 |
+
echo "应用首页: http://localhost:7860/"
|
107 |
+
echo "健康检查: http://localhost:7860/health"
|
108 |
+
echo "清理状态: http://localhost:7860/api/cleanup/status"
|
109 |
+
|
110 |
+
echo "=== 启动完成 ==="
|
111 |
+
|
112 |
+
# 保持容器运行
|
113 |
+
echo "保持服务运行..."
|
114 |
+
while true; do
|
115 |
+
# 检查关键服务是否还在运行
|
116 |
+
if ! pgrep apache2 > /dev/null; then
|
117 |
+
echo "Apache 服务已停止,重新启动..."
|
118 |
+
apache2ctl start
|
119 |
+
fi
|
120 |
+
|
121 |
+
if ! kill -0 $PYTHON_PID 2>/dev/null; then
|
122 |
+
echo "Python 应用已停止,重新启动..."
|
123 |
+
cd /app
|
124 |
+
python3 app.py &
|
125 |
+
PYTHON_PID=$!
|
126 |
+
fi
|
127 |
+
|
128 |
+
if ! pgrep cron > /dev/null; then
|
129 |
+
echo "Cron 服务已停止,重新启动..."
|
130 |
+
service cron start
|
131 |
+
fi
|
132 |
+
|
133 |
+
sleep 30
|
134 |
+
done
|