mirror of
https://github.com/arch3rPro/1Panel-Appstore.git
synced 2026-04-15 00:17:12 +08:00
Compare commits
3 Commits
e1104e4dcf
...
1632a44057
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1632a44057 | ||
|
|
1bf528acc8 | ||
|
|
69ad9e1a76 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,3 +10,5 @@
|
|||||||
# Update
|
# Update
|
||||||
/update
|
/update
|
||||||
|
|
||||||
|
# Skills
|
||||||
|
.trae
|
||||||
129
README.md
129
README.md
@@ -18,15 +18,89 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
### 📖 仓库介绍
|
### 📖 仓库介绍
|
||||||
- 本仓库包含多个适用于 1Panel 的应用,旨在为用户提供简单、快速的安装与更新体验。应用均为开源项目,支持通过 1Panel 的计划任务功能自动化安装和更新。通过仓库提供的脚本,可以轻松地将应用集成到 1Panel 系统中。
|
|
||||||
- 仓库主打优质应用合集,不追求大而全(很多基本用不上的应用会干扰检索查看),有推荐的应用可以在issue中进行提交
|
- 本仓库包含多个适用于 1Panel 的应用,旨在为用户提供简单、快速的安装与更新体验。应用均为开源项目,支持通过 1Panel 的计划任务功能自动化安装和更新。通过仓库提供的脚本,可以轻松地将应用集成到 1Panel 系统中。
|
||||||
|
- 仓库主打优质应用合集,不追求大而全(很多基本用不上的应用会干扰检索查看),有推荐的应用可以在issue中进行提交
|
||||||
|
|
||||||
### ⚠️ 仓库申明
|
### ⚠️ 仓库申明
|
||||||
|
|
||||||
|
|
||||||
- 非官方,第三方应用商店
|
- 非官方,第三方应用商店
|
||||||
- 不对任何原始镜像的有效性做出任何明示或暗示的保证或声明,安全性和风险自查
|
- 不对任何原始镜像的有效性做出任何明示或暗示的保证或声明,安全性和风险自查
|
||||||
- 个人仓库,可以Fork后自行更新,但是严禁未经授权,私自删除个人信息后合并发布
|
- 个人仓库,可以Fork后自行更新,但是严禁未经授权,私自删除个人信息后合并发布
|
||||||
|
|
||||||
|
|
||||||
|
### 🚀 使用方法
|
||||||
|
|
||||||
|
#### 📋 添加脚本到 1Panel 计划任务
|
||||||
|
|
||||||
|
1. 在 1Panel 控制面板中,进入"计划任务"页面。
|
||||||
|
2. 点击"新增任务",选择任务类型为"Shell 脚本"。
|
||||||
|
3. 在脚本框中粘贴以下代码:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 清理旧的临时目录
|
||||||
|
rm -rf /tmp/appstore_merge
|
||||||
|
|
||||||
|
# 克隆 appstore-arch3rPro
|
||||||
|
git clone --depth=1 https://ghfast.top/https://github.com/arch3rPro/1Panel-Appstore /tmp/appstore_merge/appstore-arch3rPro
|
||||||
|
|
||||||
|
# 复制 数据(完整复制)
|
||||||
|
cp -rf /tmp/appstore_merge/appstore-arch3rPro/apps/* /opt/1panel/resource/apps/local/
|
||||||
|
|
||||||
|
# 清理临时目录
|
||||||
|
rm -rf /tmp/appstore_merge
|
||||||
|
echo "应用商店数据已更新"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🤖 使用 AI 快速生成应用配置
|
||||||
|
|
||||||
|
本仓库提供了 Skill 配置,支持在 Cursor、Windsurf、Claude Code 等 AI 客户端中快速生成 1Panel 应用配置。
|
||||||
|
|
||||||
|
#### 📁 Skills 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
skills/
|
||||||
|
├── SKILL.md # 1Panel App Builder 技能定义
|
||||||
|
├── README.md # 使用文档
|
||||||
|
├── templates/ # 配置模板
|
||||||
|
│ ├── data.yml.tpl # 应用元数据模板
|
||||||
|
│ └── docker-compose.yml.tpl # 编排文件模板
|
||||||
|
├── scripts/ # 工具脚本
|
||||||
|
│ ├── generate-app.sh # 主生成脚本
|
||||||
|
│ ├── download-icon.sh # 图标下载工具
|
||||||
|
│ └── validate-app.sh # 配置验证工具
|
||||||
|
├── references/ # 参考示例
|
||||||
|
│ └── 1panel-examples.md
|
||||||
|
└── examples/ # 使用示例
|
||||||
|
└── example-usage.md
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 💡 使用示例
|
||||||
|
|
||||||
|
只需向 AI 提供以下任一信息,即可自动生成完整的应用配置:
|
||||||
|
|
||||||
|
```
|
||||||
|
# GitHub 项目
|
||||||
|
添加应用 AList https://github.com/alist-org/alist
|
||||||
|
|
||||||
|
# docker-compose 文件
|
||||||
|
根据这个 docker-compose.yml 生成 1Panel 应用配置
|
||||||
|
|
||||||
|
# docker run 命令
|
||||||
|
将这个 docker run 命令转换为 1Panel 应用:
|
||||||
|
docker run -d --name=nginx -p 80:80 nginx:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ✨ AI 生成的配置包含
|
||||||
|
|
||||||
|
- `data.yml` - 应用元数据(顶层)
|
||||||
|
- `version/data.yml` - 参数定义(表单字段)
|
||||||
|
- `docker-compose.yml` - Docker 编排文件
|
||||||
|
- `README.md` - 中文文档
|
||||||
|
- `README_en.md` - 英文文档
|
||||||
|
- `logo.png` - 应用图标
|
||||||
|
|
||||||
|
|
||||||
### 📱 应用列表
|
### 📱 应用列表
|
||||||
@@ -36,14 +110,10 @@
|
|||||||
#### 🤖LLM免费API接口
|
#### 🤖LLM免费API接口
|
||||||
|
|
||||||
- 支持一键部署AI免费API接口,使用方式请参考应用内**README介绍**
|
- 支持一键部署AI免费API接口,使用方式请参考应用内**README介绍**
|
||||||
|
|
||||||
- **Free-API系列应用已下架,原项目由于供应链投毒,被植入恶意代码,请及时停止运行并删除这些服务!!!**
|
- **Free-API系列应用已下架,原项目由于供应链投毒,被植入恶意代码,请及时停止运行并删除这些服务!!!**
|
||||||
|
|
||||||
- 经过几天的排查和重构,已重新上架[GLM-Free-API](https://github.com/xiaoY233/GLM-Free-API)、[MiniMax-Free-API](https://github.com/xiaoY233/MiniMax-Free-API)、[Qwen-Free-API](https://github.com/xiaoY233/Qwen-Free-API)、[Kimi-Free-API](https://github.com/xiaoY233/Kimi-Free-API),[DeepSeek-Free-API](https://github.com/xiaoY233/DeepSeek-Free-API),欢迎各位对源码进行审查,如果不放心,建议还是暂停使用!
|
- 经过几天的排查和重构,已重新上架[GLM-Free-API](https://github.com/xiaoY233/GLM-Free-API)、[MiniMax-Free-API](https://github.com/xiaoY233/MiniMax-Free-API)、[Qwen-Free-API](https://github.com/xiaoY233/Qwen-Free-API)、[Kimi-Free-API](https://github.com/xiaoY233/Kimi-Free-API),[DeepSeek-Free-API](https://github.com/xiaoY233/DeepSeek-Free-API),欢迎各位对源码进行审查,如果不放心,建议还是暂停使用!
|
||||||
|
|
||||||
- 其他的Free-API系列看情况再搞了,后续主要更新上述几个Free-API兼容Gemini-cli和Claude的API接入。
|
- 其他的Free-API系列看情况再搞了,后续主要更新上述几个Free-API兼容Gemini-cli和Claude的API接入。
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="33%" align="center">
|
<td width="33%" align="center">
|
||||||
@@ -103,8 +173,8 @@
|
|||||||
|
|
||||||
<!-- <a href="./apps/jimeng-free-api/README.md">
|
<!-- <a href="./apps/jimeng-free-api/README.md">
|
||||||
<img src="./apps/jimeng-free-api/logo.png" width="60" height="60" alt="Jimeng-Free-API"> -->
|
<img src="./apps/jimeng-free-api/logo.png" width="60" height="60" alt="Jimeng-Free-API"> -->
|
||||||
<br><b>Jimeng-Free-API</b>
|
|
||||||
</a>
|
<b>Jimeng-Free-API</b> </a>
|
||||||
|
|
||||||
🚀 即梦3.0逆向API【特长:图像生成顶流】
|
🚀 即梦3.0逆向API【特长:图像生成顶流】
|
||||||
|
|
||||||
@@ -115,8 +185,8 @@
|
|||||||
|
|
||||||
<!-- <a href="./apps/spark-free-api/README.md">
|
<!-- <a href="./apps/spark-free-api/README.md">
|
||||||
<img src="./apps/spark-free-api/logo.png" width="60" height="60" alt="Spark-Free-API"> -->
|
<img src="./apps/spark-free-api/logo.png" width="60" height="60" alt="Spark-Free-API"> -->
|
||||||
<br><b>Spark-Free-API</b>
|
|
||||||
</a>
|
<b>Spark-Free-API</b> </a>
|
||||||
|
|
||||||
🚀 讯飞星火大模型逆向API【特长:办公助手】
|
🚀 讯飞星火大模型逆向API【特长:办公助手】
|
||||||
|
|
||||||
@@ -144,8 +214,8 @@
|
|||||||
|
|
||||||
<!-- <a href="./apps/step-free-api/README.md">
|
<!-- <a href="./apps/step-free-api/README.md">
|
||||||
<img src="./apps/step-free-api/logo.png" width="60" height="60" alt="Step-Free-API"> -->
|
<img src="./apps/step-free-api/logo.png" width="60" height="60" alt="Step-Free-API"> -->
|
||||||
<br><b>Step-Free-API</b>
|
|
||||||
</a>
|
<b>Step-Free-API</b> </a>
|
||||||
|
|
||||||
🚀 阶跃星辰跃问Step 多模态大模型逆向API【特长:超强多模态】
|
🚀 阶跃星辰跃问Step 多模态大模型逆向API【特长:超强多模态】
|
||||||
|
|
||||||
@@ -156,8 +226,8 @@
|
|||||||
|
|
||||||
<!-- <a href="./apps/metaso-free-api/README.md">
|
<!-- <a href="./apps/metaso-free-api/README.md">
|
||||||
<img src="./apps/metaso-free-api/logo.png" width="60" height="60" alt="Metaso-Free-API"> -->
|
<img src="./apps/metaso-free-api/logo.png" width="60" height="60" alt="Metaso-Free-API"> -->
|
||||||
<br><b>Metaso-Free-API</b>
|
|
||||||
</a>
|
<b>Metaso-Free-API</b> </a>
|
||||||
|
|
||||||
🚀 秘塔AI搜索逆向API【特长:超强检索超长输出】
|
🚀 秘塔AI搜索逆向API【特长:超强检索超长输出】
|
||||||
|
|
||||||
@@ -208,7 +278,6 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
#### 📝 文档与内容管理
|
#### 📝 文档与内容管理
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
@@ -1197,33 +1266,7 @@ AI驱动的开源代码知识库与文档协作平台,支持多模型、多数
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### 🚀 使用方法
|
|
||||||
|
|
||||||
#### 📋 添加脚本到 1Panel 计划任务
|
|
||||||
|
|
||||||
1. 在 1Panel 控制面板中,进入"计划任务"页面。
|
|
||||||
2. 点击"新增任务",选择任务类型为"Shell 脚本"。
|
|
||||||
3. 在脚本框中粘贴以下代码:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# 清理旧的临时目录
|
|
||||||
rm -rf /tmp/appstore_merge
|
|
||||||
|
|
||||||
# 克隆 appstore-arch3rPro
|
|
||||||
git clone --depth=1 https://ghfast.top/https://github.com/arch3rPro/1Panel-Appstore /tmp/appstore_merge/appstore-arch3rPro
|
|
||||||
|
|
||||||
# 复制 数据(完整复制)
|
|
||||||
cp -rf /tmp/appstore_merge/appstore-arch3rPro/apps/* /opt/1panel/resource/apps/local/
|
|
||||||
|
|
||||||
# 清理临时目录
|
|
||||||
rm -rf /tmp/appstore_merge
|
|
||||||
echo "应用商店数据已更新"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 橙色风格 -->
|
<!-- 橙色风格 -->
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
61
apps/sub2api/README.md
Normal file
61
apps/sub2api/README.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# Sub2API
|
||||||
|
|
||||||
|
AI API 网关平台,用于分发和管理 AI 产品订阅的 API 配额。
|
||||||
|
|
||||||
|
## 功能特点
|
||||||
|
|
||||||
|
- 多账号管理 - 支持多种上游账号类型(OAuth、API Key)
|
||||||
|
- API Key 分发 - 为用户生成和管理 API Key
|
||||||
|
- 精确计费 - Token 级别使用追踪和费用计算
|
||||||
|
- 智能调度 - 智能账号选择,支持粘性会话
|
||||||
|
- 并发控制 - 支持用户级和账号级并发限制
|
||||||
|
- 限流 - 可配置的请求和 Token 限流
|
||||||
|
- 管理后台 - Web 界面用于监控和管理
|
||||||
|
- 外部系统集成 - 支持通过 iframe 嵌入外部系统
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 默认端口
|
||||||
|
|
||||||
|
- Web 界面: 8080
|
||||||
|
|
||||||
|
### 初始化配置
|
||||||
|
|
||||||
|
部署完成后,访问 `http://YOUR_SERVER_IP:8080` 进入设置向导。
|
||||||
|
|
||||||
|
**数据库连接设置:**
|
||||||
|
- PostgreSQL 主机: `postgres`(Docker 网络内使用服务名,不是 localhost)
|
||||||
|
- Redis 主机: `redis`(Docker 网络内使用服务名,不是 localhost)
|
||||||
|
- PostgreSQL 密码: 请使用强密码
|
||||||
|
|
||||||
|
**JWT 密钥要求:**
|
||||||
|
- 长度必须至少 32 字符
|
||||||
|
- 生产环境请使用随机生成的强密码
|
||||||
|
|
||||||
|
### 数据目录
|
||||||
|
|
||||||
|
应用数据存储在 Docker 命名卷中:
|
||||||
|
- `postgres_data` - PostgreSQL 数据库数据
|
||||||
|
- `redis_data` - Redis 缓存数据
|
||||||
|
- `./data` - 应用配置和数据
|
||||||
|
|
||||||
|
## 相关链接
|
||||||
|
|
||||||
|
- 官方网站: https://sub2api.org
|
||||||
|
- GitHub: https://github.com/Wei-Shaw/sub2api
|
||||||
|
- 在线演示: https://demo.sub2api.org/
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **数据库连接**:在 Docker 部署中,PostgreSQL 和 Redis 使用服务名(`postgres`、`redis`)进行连接,请勿使用 `localhost`
|
||||||
|
|
||||||
|
2. **JWT 密钥**:必须至少 32 字符,建议使用随机字符串
|
||||||
|
|
||||||
|
3. **首次部署**:如果遇到数据库连接错误,请确保:
|
||||||
|
- PostgreSQL 容器已完全启动(等待约 10-30 秒)
|
||||||
|
- 旧的损坏数据卷已清除(使用 `docker compose down -v`)
|
||||||
|
|
||||||
|
4. **安全提醒**:
|
||||||
|
- 本项目仅供个人学习使用
|
||||||
|
- 使用者必须在遵循 Anthropic、OpenAI 等服务条款的情况下使用
|
||||||
|
- 请勿用于非法用途
|
||||||
61
apps/sub2api/README_en.md
Normal file
61
apps/sub2api/README_en.md
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# Sub2API
|
||||||
|
|
||||||
|
AI API Gateway Platform for subscription quota distribution.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Multi-Account Management - Support multiple upstream account types (OAuth, API Key)
|
||||||
|
- API Key Distribution - Generate and manage API Keys for users
|
||||||
|
- Precise Billing - Token-level usage tracking and cost calculation
|
||||||
|
- Smart Scheduling - Intelligent account selection with sticky sessions
|
||||||
|
- Concurrency Control - Per-user and per-account concurrency limits
|
||||||
|
- Rate Limiting - Configurable request and token rate limits
|
||||||
|
- Admin Dashboard - Web interface for monitoring and management
|
||||||
|
- External System Integration - Embed external systems via iframe
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Default Port
|
||||||
|
|
||||||
|
- Web UI: 8080
|
||||||
|
|
||||||
|
### Initial Setup
|
||||||
|
|
||||||
|
After deployment, access `http://YOUR_SERVER_IP:8080` to run the setup wizard.
|
||||||
|
|
||||||
|
**Database Connection Settings:**
|
||||||
|
- PostgreSQL Host: `postgres` (use service name in Docker network, NOT localhost)
|
||||||
|
- Redis Host: `redis` (use service name in Docker network, NOT localhost)
|
||||||
|
- PostgreSQL Password: Please use a strong password
|
||||||
|
|
||||||
|
**JWT Secret Requirements:**
|
||||||
|
- Length must be at least 32 characters
|
||||||
|
- Use a randomly generated strong password for production
|
||||||
|
|
||||||
|
### Data Directory
|
||||||
|
|
||||||
|
Application data is stored in Docker named volumes:
|
||||||
|
- `postgres_data` - PostgreSQL database data
|
||||||
|
- `redis_data` - Redis cache data
|
||||||
|
- `./data` - Application configuration and data
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Website: https://sub2api.org
|
||||||
|
- GitHub: https://github.com/Wei-Shaw/sub2api
|
||||||
|
- Demo: https://demo.sub2api.org/
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
|
||||||
|
1. **Database Connection**: In Docker deployment, PostgreSQL and Redis use service names (`postgres`, `redis`) for connection. Do NOT use `localhost`
|
||||||
|
|
||||||
|
2. **JWT Secret**: Must be at least 32 characters, use a random string recommended
|
||||||
|
|
||||||
|
3. **First Deployment**: If you encounter database connection errors, ensure:
|
||||||
|
- PostgreSQL container has fully started (wait about 10-30 seconds)
|
||||||
|
- Old corrupted data volumes are cleared (use `docker compose down -v`)
|
||||||
|
|
||||||
|
4. **Disclaimer**:
|
||||||
|
- This project is for personal learning purposes only
|
||||||
|
- Users must comply with the Terms of Service of Anthropic, OpenAI, etc.
|
||||||
|
- Do not use for illegal purposes
|
||||||
22
apps/sub2api/data.yml
Normal file
22
apps/sub2api/data.yml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Sub2API
|
||||||
|
tags:
|
||||||
|
- AI / 大模型
|
||||||
|
title: Sub2API - AI API 网关平台
|
||||||
|
description: Sub2API - AI API 网关平台
|
||||||
|
additionalProperties:
|
||||||
|
key: sub2api
|
||||||
|
name: Sub2API
|
||||||
|
tags:
|
||||||
|
- AI
|
||||||
|
shortDescZh: AI API 网关平台,支持订阅配额分发、API Key 管理、计费和负载均衡
|
||||||
|
shortDescEn: AI API gateway platform for subscription quota distribution
|
||||||
|
type: website
|
||||||
|
crossVersionUpdate: true
|
||||||
|
limit: 0
|
||||||
|
recommend: 0
|
||||||
|
website: https://sub2api.org
|
||||||
|
github: https://github.com/Wei-Shaw/sub2api
|
||||||
|
document: https://github.com/Wei-Shaw/sub2api
|
||||||
|
architectures:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
20
apps/sub2api/latest/config.yaml
Normal file
20
apps/sub2api/latest/config.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
server:
|
||||||
|
host: "0.0.0.0"
|
||||||
|
port: 8080
|
||||||
|
mode: "release"
|
||||||
|
|
||||||
|
database:
|
||||||
|
host: "postgres"
|
||||||
|
port: 5432
|
||||||
|
user: "sub2api"
|
||||||
|
password: "${POSTGRES_PASSWORD}"
|
||||||
|
dbname: "sub2api"
|
||||||
|
|
||||||
|
redis:
|
||||||
|
host: "redis"
|
||||||
|
port: 6379
|
||||||
|
password: ""
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
secret: "sub2api_jwt_secret_change_in_production_32chars"
|
||||||
|
expire_hour: 24
|
||||||
33
apps/sub2api/latest/data.yml
Normal file
33
apps/sub2api/latest/data.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
additionalProperties:
|
||||||
|
formFields:
|
||||||
|
- default: 8080
|
||||||
|
edit: true
|
||||||
|
envKey: PANEL_APP_PORT_HTTP
|
||||||
|
labelEn: Web Port
|
||||||
|
labelZh: Web 端口
|
||||||
|
required: true
|
||||||
|
rule: paramPort
|
||||||
|
type: number
|
||||||
|
- default: Asia/Shanghai
|
||||||
|
edit: true
|
||||||
|
envKey: TZ
|
||||||
|
labelEn: Time Zone
|
||||||
|
labelZh: 时区
|
||||||
|
required: true
|
||||||
|
type: text
|
||||||
|
- default: sub2api_secure_jwt_secret_change_in_production
|
||||||
|
edit: true
|
||||||
|
envKey: JWT_SECRET
|
||||||
|
labelEn: JWT Secret
|
||||||
|
labelZh: JWT 密钥
|
||||||
|
required: true
|
||||||
|
rule: paramCommon
|
||||||
|
type: password
|
||||||
|
- default: sub2api_secure_db_password_change_in_production
|
||||||
|
edit: true
|
||||||
|
envKey: POSTGRES_PASSWORD
|
||||||
|
labelEn: PostgreSQL Password
|
||||||
|
labelZh: PostgreSQL 密码
|
||||||
|
required: true
|
||||||
|
rule: paramCommon
|
||||||
|
type: password
|
||||||
0
apps/sub2api/latest/data/.gitkeep
Normal file
0
apps/sub2api/latest/data/.gitkeep
Normal file
26
apps/sub2api/latest/data/config.yml
Normal file
26
apps/sub2api/latest/data/config.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
server:
|
||||||
|
host: "0.0.0.0"
|
||||||
|
port: 8080
|
||||||
|
mode: "release"
|
||||||
|
|
||||||
|
database:
|
||||||
|
host: "postgres"
|
||||||
|
port: 5432
|
||||||
|
user: "sub2api"
|
||||||
|
password: "${POSTGRES_PASSWORD}"
|
||||||
|
dbname: "sub2api"
|
||||||
|
|
||||||
|
redis:
|
||||||
|
host: "redis"
|
||||||
|
port: 6379
|
||||||
|
password: ""
|
||||||
|
|
||||||
|
jwt:
|
||||||
|
secret: "${JWT_SECRET}"
|
||||||
|
expire_hour: 24
|
||||||
|
|
||||||
|
default:
|
||||||
|
user_concurrency: 5
|
||||||
|
user_balance: 0
|
||||||
|
api_key_prefix: "sk-"
|
||||||
|
rate_multiplier: 1.0
|
||||||
57
apps/sub2api/latest/docker-compose.yml
Normal file
57
apps/sub2api/latest/docker-compose.yml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
services:
|
||||||
|
sub2api:
|
||||||
|
image: weishaw/sub2api:latest
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:8080"
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data
|
||||||
|
- ./config.yaml:/app/config.yaml:ro
|
||||||
|
environment:
|
||||||
|
- TZ=${TZ}
|
||||||
|
- POSTGRES_CONN_STRING=postgres://sub2api:${POSTGRES_PASSWORD}@postgres:5432/sub2api?sslmode=disable
|
||||||
|
- REDIS_CONN_STRING=redis://redis:6379/0
|
||||||
|
- JWT_SECRET=${JWT_SECRET}
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
- redis
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
container_name: ${CONTAINER_NAME}-postgres
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=sub2api
|
||||||
|
- POSTGRES_USER=sub2api
|
||||||
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: ${CONTAINER_NAME}-redis
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
volumes:
|
||||||
|
- redis_data:/data
|
||||||
|
command: redis-server --appendonly yes
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
|
redis_data:
|
||||||
BIN
apps/sub2api/logo.png
Normal file
BIN
apps/sub2api/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 146 KiB |
200
skills/README.md
Normal file
200
skills/README.md
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
# 1Panel App Builder
|
||||||
|
|
||||||
|
快速生成符合 1Panel 本地应用商店规范的 APP 配置文件。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- ✅ 支持多种输入源(GitHub、docker-compose、docker run、本地文件)
|
||||||
|
- ✅ 自动抽取应用信息并生成标准化配置
|
||||||
|
- ✅ 自动下载应用图标(支持多个图标源)
|
||||||
|
- ✅ 生成中英文 README
|
||||||
|
- ✅ 符合 1Panel 应用商店规范
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
1panel-app-builder/
|
||||||
|
├── SKILL.md # 技能定义文件
|
||||||
|
├── README.md # 使用文档
|
||||||
|
├── templates/ # 配置模板
|
||||||
|
│ ├── data.yml.tpl # 应用元数据模板
|
||||||
|
│ └── docker-compose.yml.tpl # 编排文件模板
|
||||||
|
├── scripts/ # 工具脚本
|
||||||
|
│ ├── generate-app.sh # 主生成脚本
|
||||||
|
│ └── download-icon.sh # 图标下载工具
|
||||||
|
└── examples/ # 使用示例
|
||||||
|
└── example-usage.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 1. 基本用法
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# GitHub 项目
|
||||||
|
./scripts/generate-app.sh https://github.com/alist-org/alist
|
||||||
|
|
||||||
|
# docker-compose 文件链接
|
||||||
|
./scripts/generate-app.sh https://raw.githubusercontent.com/.../docker-compose.yml
|
||||||
|
|
||||||
|
# docker run 命令
|
||||||
|
./scripts/generate-app.sh "docker run -d --name=alist -p 5244:5244 xhofe/alist:v3.45.0"
|
||||||
|
|
||||||
|
# 本地文件
|
||||||
|
./scripts/generate-app.sh ./my-docker-compose.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 输出示例
|
||||||
|
|
||||||
|
```
|
||||||
|
./apps/alist/v3.45.0/
|
||||||
|
├── data.yml # 应用元数据
|
||||||
|
├── docker-compose.yml # 编排文件
|
||||||
|
├── logo.png # 应用图标
|
||||||
|
├── README.md # 中文简介
|
||||||
|
└── README_en.md # 英文简介
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 生成的配置文件
|
||||||
|
|
||||||
|
#### data.yml 示例
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: AList
|
||||||
|
tags:
|
||||||
|
- 实用工具
|
||||||
|
- 云存储
|
||||||
|
title: 支持多存储的文件列表程序和私人网盘
|
||||||
|
description: 支持多存储的文件列表程序和私人网盘
|
||||||
|
additionalProperties:
|
||||||
|
key: alist
|
||||||
|
name: AList
|
||||||
|
tags:
|
||||||
|
- Storage
|
||||||
|
- Tool
|
||||||
|
shortDescZh: 支持多存储的文件列表程序和私人网盘
|
||||||
|
shortDescEn: Supporting multi-storage file listing program
|
||||||
|
website: https://alist.nn.ci/
|
||||||
|
github: https://github.com/alist-org/alist
|
||||||
|
architectures:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
```
|
||||||
|
|
||||||
|
#### docker-compose.yml 示例
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
alist:
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:5244"
|
||||||
|
volumes:
|
||||||
|
- ./data/data:/opt/alist/data
|
||||||
|
environment:
|
||||||
|
- PUID=0
|
||||||
|
- PGID=0
|
||||||
|
- UMASK=022
|
||||||
|
image: xhofe/alist:v3.45.0
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## 高级用法
|
||||||
|
|
||||||
|
### 指定输出目录
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/generate-app.sh https://github.com/alist-org/alist ./my-apps
|
||||||
|
```
|
||||||
|
|
||||||
|
### 单独下载图标
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/download-icon.sh alist ./logo.png 200
|
||||||
|
```
|
||||||
|
|
||||||
|
### 图标源优先级
|
||||||
|
|
||||||
|
1. [Dashboard Icons](https://dashboardicons.com/icons)
|
||||||
|
2. [Simple Icons](https://simpleicons.org/)
|
||||||
|
3. [selfh.st Icons](https://selfh.st/icons/)
|
||||||
|
|
||||||
|
## 依赖工具
|
||||||
|
|
||||||
|
必需:
|
||||||
|
- `bash` - 脚本执行环境
|
||||||
|
- `curl` - HTTP 请求
|
||||||
|
- `jq` - JSON 解析
|
||||||
|
- `yq` - YAML 解析(可选,用于高级解析)
|
||||||
|
|
||||||
|
可选:
|
||||||
|
- `ImageMagick` (convert) - 图标尺寸调整
|
||||||
|
- `sips` (macOS) - 图标尺寸调整
|
||||||
|
- `tree` - 目录树显示
|
||||||
|
|
||||||
|
## 配置模板说明
|
||||||
|
|
||||||
|
### data.yml 模板变量
|
||||||
|
|
||||||
|
| 变量 | 说明 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| `${APP_NAME}` | 应用名称 | AList |
|
||||||
|
| `${APP_KEY}` | 应用键名 | alist |
|
||||||
|
| `${TITLE_ZH}` | 中文标题 | 文件列表程序 |
|
||||||
|
| `${DESC_ZH}` | 中文描述 | 支持多存储... |
|
||||||
|
| `${TAG_1}` | 标签1 | 实用工具 |
|
||||||
|
| `${WEBSITE}` | 官网 | https://alist.nn.ci/ |
|
||||||
|
| `${GITHUB}` | GitHub | https://github.com/alist-org/alist |
|
||||||
|
|
||||||
|
### docker-compose.yml 模板变量
|
||||||
|
|
||||||
|
| 变量 | 说明 | 示例 |
|
||||||
|
|------|------|------|
|
||||||
|
| `${SERVICE_NAME}` | 服务名 | alist |
|
||||||
|
| `${IMAGE}` | 镜像名 | xhofe/alist |
|
||||||
|
| `${TAG}` | 镜像标签 | v3.45.0 |
|
||||||
|
| `${PORT}` | 端口 | 5244 |
|
||||||
|
|
||||||
|
## 下一步操作
|
||||||
|
|
||||||
|
生成配置后:
|
||||||
|
|
||||||
|
1. ✅ 检查 `data.yml` 中的应用信息是否准确
|
||||||
|
2. ✅ 补充完善应用描述和标签
|
||||||
|
3. ✅ 替换 `logo.png` 为合适的应用图标
|
||||||
|
4. ✅ 测试 `docker-compose.yml` 是否正常工作
|
||||||
|
5. ✅ 提交到 1Panel 应用商店仓库
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### Q: 图标下载失败怎么办?
|
||||||
|
|
||||||
|
A: 手动从以下网站下载图标:
|
||||||
|
- https://dashboardicons.com/icons?q=<应用名>
|
||||||
|
- https://simpleicons.org/?q=<应用名>
|
||||||
|
- https://selfh.st/icons/
|
||||||
|
|
||||||
|
### Q: 如何处理多服务应用?
|
||||||
|
|
||||||
|
A: 生成后手动编辑 `docker-compose.yml`,添加其他服务。
|
||||||
|
|
||||||
|
### Q: 版本号如何确定?
|
||||||
|
|
||||||
|
A: 默认从镜像标签提取,也可手动指定。
|
||||||
|
|
||||||
|
## 参考资源
|
||||||
|
|
||||||
|
- [1Panel 官方文档](https://1panel.cn/docs/)
|
||||||
|
- [1Panel 应用商店仓库](https://github.com/1Panel-dev/appstore)
|
||||||
|
- [Docker Compose 文档](https://docs.docker.com/compose/)
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
MIT License
|
||||||
404
skills/SKILL.md
Normal file
404
skills/SKILL.md
Normal file
@@ -0,0 +1,404 @@
|
|||||||
|
---
|
||||||
|
name: 1panel-app-builder
|
||||||
|
description: >
|
||||||
|
Build 1Panel local app store configurations from Docker deployments. Use when:
|
||||||
|
- User provides a GitHub project link and wants to add it to 1Panel app store
|
||||||
|
- User has a docker-compose.yml or docker run command and needs 1Panel app format
|
||||||
|
- User wants to create a local app for 1Panel panel
|
||||||
|
- User mentions "1Panel app", "1Panel 应用商店", "本地应用", "app store", or similar
|
||||||
|
|
||||||
|
Supports: GitHub repos, Docker Hub images, docker-compose files, docker run commands.
|
||||||
|
Output: Complete app folder with data.yml, docker-compose.yml, logo.png, README.md
|
||||||
|
|
||||||
|
Always use this skill for 1Panel app packaging - it knows the exact directory structure,
|
||||||
|
variable naming conventions (PANEL_APP_PORT_HTTP, CONTAINER_NAME), and 1panel-network
|
||||||
|
requirements that are easy to get wrong without guidance.
|
||||||
|
---
|
||||||
|
|
||||||
|
# 1Panel App Store Builder
|
||||||
|
|
||||||
|
Transform Docker deployments into 1Panel-compatible local app store packages.
|
||||||
|
|
||||||
|
## Understanding 1Panel App Structure
|
||||||
|
|
||||||
|
A valid 1Panel app follows this directory structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
app-key/ # App identifier (lowercase, hyphenated)
|
||||||
|
├── logo.png # App icon (64x64 or 128x128 recommended)
|
||||||
|
├── data.yml # App metadata (top-level)
|
||||||
|
├── README.md # Chinese documentation
|
||||||
|
├── README_en.md # English documentation (optional)
|
||||||
|
└── 1.0.0/ # Version directory (semver or "latest")
|
||||||
|
├── data.yml # Parameter definitions (form fields)
|
||||||
|
├── docker-compose.yml # Compose file with variable substitution
|
||||||
|
├── data/ # Persistent data directory
|
||||||
|
└── scripts/ # Optional scripts
|
||||||
|
└── upgrade.sh # Upgrade script
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step-by-Step Workflow
|
||||||
|
|
||||||
|
### Step 1: Gather Source Information
|
||||||
|
|
||||||
|
Based on user input type, extract Docker deployment details:
|
||||||
|
|
||||||
|
**From GitHub Link:**
|
||||||
|
1. Fetch the GitHub repository README.md
|
||||||
|
2. Look for Docker installation instructions (docker run, docker-compose)
|
||||||
|
3. Extract: image name, ports, volumes, environment variables
|
||||||
|
4. Note: project name, description, official website, supported architectures
|
||||||
|
|
||||||
|
**From docker-compose.yml:**
|
||||||
|
1. Parse all services defined
|
||||||
|
2. Extract: image versions, port mappings, volume mounts, environment variables
|
||||||
|
3. Identify the main service (typically the one with web UI)
|
||||||
|
|
||||||
|
**From docker run command:**
|
||||||
|
1. Parse flags: `-p` (ports), `-v` (volumes), `-e` (env vars), `--name`
|
||||||
|
2. Extract the image name and tag
|
||||||
|
3. Identify exposed ports and data directories
|
||||||
|
|
||||||
|
### Step 2: Generate App Key and Metadata
|
||||||
|
|
||||||
|
**App Key Rules:**
|
||||||
|
- Lowercase only
|
||||||
|
- Use hyphens for multi-word names
|
||||||
|
- Keep it short but descriptive
|
||||||
|
- Examples: `alist`, `it-tools`, `n8n-zh`, `lobe-chat-data`
|
||||||
|
|
||||||
|
**Required Metadata (top-level data.yml):**
|
||||||
|
```yaml
|
||||||
|
name: AppName # Display name (can have capitals)
|
||||||
|
tags: # Chinese tags for categorization
|
||||||
|
- 开发工具
|
||||||
|
- 实用工具
|
||||||
|
title: Brief Chinese description
|
||||||
|
description: Same as title
|
||||||
|
additionalProperties:
|
||||||
|
key: app-key # Must match directory name
|
||||||
|
name: AppName # Same as name above
|
||||||
|
tags: # English tags
|
||||||
|
- DevTool
|
||||||
|
- Utility
|
||||||
|
shortDescZh: Chinese description
|
||||||
|
shortDescEn: English description
|
||||||
|
description:
|
||||||
|
en: Full English description
|
||||||
|
zh: Full Chinese description
|
||||||
|
# Add more languages if available: ja, ko, ru, pt-br, ms, zh-Hant
|
||||||
|
type: website # or "runtime" for databases, "tool" for CLI tools
|
||||||
|
crossVersionUpdate: true # Usually true
|
||||||
|
limit: 0 # 0 = unlimited instances
|
||||||
|
recommend: 0 # 0-100, higher = more recommended
|
||||||
|
website: https://example.com # Official website
|
||||||
|
github: https://github.com/org/repo
|
||||||
|
document: https://docs.example.com
|
||||||
|
architectures: # Supported CPU architectures
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
# Add: arm/v7, arm/v6, s390x if supported
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Define Parameters (version/data.yml)
|
||||||
|
|
||||||
|
Parameters become UI form fields in 1Panel. Define user-configurable values:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
additionalProperties:
|
||||||
|
formFields:
|
||||||
|
# Port parameter example
|
||||||
|
- default: 8080
|
||||||
|
edit: true
|
||||||
|
envKey: PANEL_APP_PORT_HTTP # Variable name used in docker-compose
|
||||||
|
labelEn: Web Port
|
||||||
|
labelZh: Web端口
|
||||||
|
required: true
|
||||||
|
rule: paramPort # Validation rule
|
||||||
|
type: number # Field type
|
||||||
|
label: # Multi-language labels
|
||||||
|
en: Web Port
|
||||||
|
zh: Web端口
|
||||||
|
ja: Webポート
|
||||||
|
ko: Web 포트
|
||||||
|
|
||||||
|
# Text parameter example (for API keys, passwords, etc.)
|
||||||
|
- default: ""
|
||||||
|
edit: true
|
||||||
|
envKey: API_KEY
|
||||||
|
labelEn: API Key
|
||||||
|
labelZh: API密钥
|
||||||
|
required: false
|
||||||
|
rule: paramCommon
|
||||||
|
type: text
|
||||||
|
|
||||||
|
# Password parameter example
|
||||||
|
- default: "changeme"
|
||||||
|
edit: true
|
||||||
|
envKey: ADMIN_PASSWORD
|
||||||
|
labelEn: Admin Password
|
||||||
|
labelZh: 管理员密码
|
||||||
|
required: true
|
||||||
|
rule: paramCommon
|
||||||
|
type: password
|
||||||
|
|
||||||
|
# Select parameter example
|
||||||
|
- default: "sqlite"
|
||||||
|
edit: true
|
||||||
|
envKey: DATABASE_TYPE
|
||||||
|
labelEn: Database Type
|
||||||
|
labelZh: 数据库类型
|
||||||
|
required: true
|
||||||
|
type: select
|
||||||
|
values:
|
||||||
|
- label: SQLite
|
||||||
|
value: sqlite
|
||||||
|
- label: PostgreSQL
|
||||||
|
value: postgres
|
||||||
|
```
|
||||||
|
|
||||||
|
**Parameter Types:**
|
||||||
|
- `number`: For ports, counts
|
||||||
|
- `text`: For API keys, URLs, names
|
||||||
|
- `password`: For secrets (masked input)
|
||||||
|
- `select`: For dropdown choices
|
||||||
|
- `boolean`: For toggle switches
|
||||||
|
|
||||||
|
**Validation Rules:**
|
||||||
|
- `paramPort`: Valid port number (1-65535)
|
||||||
|
- `paramCommon`: Non-empty string
|
||||||
|
- `paramExtUrl`: Valid URL format
|
||||||
|
- Empty string: No validation
|
||||||
|
|
||||||
|
### Step 4: Create docker-compose.yml
|
||||||
|
|
||||||
|
Convert the original Docker deployment to use variable substitution:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app-name:
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:8080"
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
image: org/image:tag
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Critical Rules:**
|
||||||
|
1. Always use `${CONTAINER_NAME}` for container_name
|
||||||
|
2. Always use `restart: always`
|
||||||
|
3. Always connect to `1panel-network` (external network)
|
||||||
|
4. Port mapping uses `PANEL_APP_PORT_*` variables from data.yml
|
||||||
|
5. Volume paths use relative `./data/` for persistence
|
||||||
|
6. Add `labels: createdBy: "Apps"`
|
||||||
|
7. Keep original environment variables but use defaults
|
||||||
|
|
||||||
|
### Step 5: Create README Files
|
||||||
|
|
||||||
|
**README.md (Chinese):**
|
||||||
|
```markdown
|
||||||
|
# AppName
|
||||||
|
|
||||||
|
简短描述应用的功能和特点。
|
||||||
|
|
||||||
|
## 功能特点
|
||||||
|
|
||||||
|
- 特点1
|
||||||
|
- 特点2
|
||||||
|
- 特点3
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
### 默认端口
|
||||||
|
|
||||||
|
- Web界面: 8080
|
||||||
|
|
||||||
|
### 默认账号密码
|
||||||
|
|
||||||
|
- 用户名: admin
|
||||||
|
- 密码: changeme (请在部署后立即修改)
|
||||||
|
|
||||||
|
### 数据目录
|
||||||
|
|
||||||
|
应用数据存储在 `./data` 目录。
|
||||||
|
|
||||||
|
## 相关链接
|
||||||
|
|
||||||
|
- 官方网站: https://example.com
|
||||||
|
- GitHub: https://github.com/org/repo
|
||||||
|
- 文档: https://docs.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
**README_en.md (English, optional):**
|
||||||
|
```markdown
|
||||||
|
# AppName
|
||||||
|
|
||||||
|
Brief description of the application.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Feature 1
|
||||||
|
- Feature 2
|
||||||
|
- Feature 3
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Default Port
|
||||||
|
|
||||||
|
- Web UI: 8080
|
||||||
|
|
||||||
|
### Default Credentials
|
||||||
|
|
||||||
|
- Username: admin
|
||||||
|
- Password: changeme (change after deployment)
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- Website: https://example.com
|
||||||
|
- GitHub: https://github.com/org/repo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 6: Download App Icon
|
||||||
|
|
||||||
|
Search and download the app logo from these sources (in order):
|
||||||
|
|
||||||
|
1. **Dashboard Icons**: https://dashboardicons.com/icons?q={app-name}
|
||||||
|
2. **Simple Icons**: https://simpleicons.org/?q={app-name}
|
||||||
|
3. **Selfh.st Icons**: https://selfh.st/icons/
|
||||||
|
|
||||||
|
Save as `logo.png` in the app root directory.
|
||||||
|
|
||||||
|
### Step 7: Create Data Directory Structure
|
||||||
|
|
||||||
|
Create the `data/` directory inside the version folder:
|
||||||
|
```bash
|
||||||
|
mkdir -p app-key/version/data
|
||||||
|
```
|
||||||
|
|
||||||
|
This directory will be mounted as a volume for persistent data.
|
||||||
|
|
||||||
|
## Quality Checklist
|
||||||
|
|
||||||
|
Before delivering the app package, verify:
|
||||||
|
|
||||||
|
- [ ] App key is lowercase with hyphens only
|
||||||
|
- [ ] All required fields in top-level data.yml are present
|
||||||
|
- [ ] Version data.yml has proper parameter definitions
|
||||||
|
- [ ] docker-compose.yml uses variable substitution correctly
|
||||||
|
- [ ] `1panel-network` is defined as external network
|
||||||
|
- [ ] Volume paths use relative `./data/` format
|
||||||
|
- [ ] README files are created with proper documentation
|
||||||
|
- [ ] Logo file exists (logo.png)
|
||||||
|
- [ ] Version directory follows semver or uses "latest"
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Database Applications
|
||||||
|
```yaml
|
||||||
|
# For apps that need a database (PostgreSQL, MySQL, etc.)
|
||||||
|
# Include database as a separate service in docker-compose
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
db:
|
||||||
|
image: postgres:15
|
||||||
|
volumes:
|
||||||
|
- ./data/db:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=appdb
|
||||||
|
- POSTGRES_USER=appuser
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multi-Service Applications
|
||||||
|
```yaml
|
||||||
|
# For apps with multiple services (frontend + backend, etc.)
|
||||||
|
services:
|
||||||
|
frontend:
|
||||||
|
image: org/frontend:tag
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:80"
|
||||||
|
backend:
|
||||||
|
image: org/backend:tag
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_API}:8080"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Applications with Reverse Proxy
|
||||||
|
```yaml
|
||||||
|
# For apps that don't expose ports directly
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
# No ports section - accessed through 1Panel's reverse proxy
|
||||||
|
expose:
|
||||||
|
- "8080"
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
```
|
||||||
|
|
||||||
|
## Automation Scripts
|
||||||
|
|
||||||
|
Use the provided scripts for faster workflow:
|
||||||
|
|
||||||
|
### generate-app.sh - 自动生成应用配置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# GitHub 项目
|
||||||
|
./scripts/generate-app.sh https://github.com/alist-org/alist
|
||||||
|
|
||||||
|
# docker-compose 文件
|
||||||
|
./scripts/generate-app.sh ./docker-compose.yml
|
||||||
|
|
||||||
|
# docker run 命令
|
||||||
|
./scripts/generate-app.sh "docker run -d --name=nginx -p 80:80 nginx:latest"
|
||||||
|
```
|
||||||
|
|
||||||
|
### download-icon.sh - 下载应用图标
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/download-icon.sh redis ./logo.png 200
|
||||||
|
```
|
||||||
|
|
||||||
|
### validate-app.sh - 验证配置完整性
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/validate-app.sh ./apps/myapp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Reference Files
|
||||||
|
|
||||||
|
- `references/1panel-examples.md` - 完整的真实应用配置示例(AList、NocoDB等)
|
||||||
|
- `examples/example-usage.md` - 使用示例和工作流程
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
**Issue**: App won't start
|
||||||
|
- Check if ports are already in use
|
||||||
|
- Verify volume permissions
|
||||||
|
- Check container logs: `docker logs ${CONTAINER_NAME}`
|
||||||
|
|
||||||
|
**Issue**: Data not persisting
|
||||||
|
- Ensure volumes are correctly mapped to `./data/`
|
||||||
|
- Check directory permissions
|
||||||
|
|
||||||
|
**Issue**: Environment variables not working
|
||||||
|
- Verify variable names match between data.yml and docker-compose.yml
|
||||||
|
- Check default values are appropriate
|
||||||
|
|
||||||
|
**Issue**: 图标下载失败
|
||||||
|
- 从以下网站手动下载:
|
||||||
|
- https://dashboardicons.com/icons?q={app-name}
|
||||||
|
- https://simpleicons.org/?q={app-name}
|
||||||
|
- https://selfh.st/icons/
|
||||||
23
skills/evals/evals.json
Normal file
23
skills/evals/evals.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"skill_name": "1panel-app-builder",
|
||||||
|
"evals": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"prompt": "帮我把这个项目打包成1Panel本地应用:https://github.com/0xJacky/nginx-ui 这是一个Nginx配置管理工具,用docker部署,默认端口是9000",
|
||||||
|
"expected_output": "Create a complete 1Panel app package for nginx-ui with proper directory structure, data.yml metadata, docker-compose.yml with variable substitution, README files, and placeholder logo",
|
||||||
|
"files": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"prompt": "我有一个docker-compose.yml文件,内容如下:\n```yaml\nversion: '3'\nservices:\n memos:\n image: neosmemo/memos:latest\n container_name: memos\n ports:\n - \"5230:5230\"\n volumes:\n - ./memos_data:/var/opt/memos\n restart: always\n```\n帮我生成1Panel应用商店的配置",
|
||||||
|
"expected_output": "Parse the docker-compose file and generate 1Panel app package for memos with converted docker-compose.yml using PANEL_APP_PORT_HTTP variable, proper data.yml with port parameter definition, and supporting files",
|
||||||
|
"files": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"prompt": "docker run -d --name umami -p 3000:3000 -e DATABASE_URL=postgresql://user:pass@db:5432/umami ghcr.io/umami-software/umami:postgresql-latest\n请帮我把这个umami网站统计工具做成1Panel应用",
|
||||||
|
"expected_output": "Parse the docker run command, extract port 3000, environment variable DATABASE_URL, and generate 1Panel app package with appropriate parameter fields for database URL configuration",
|
||||||
|
"files": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
237
skills/examples/example-usage.md
Normal file
237
skills/examples/example-usage.md
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
# 使用示例
|
||||||
|
|
||||||
|
## 示例 1:从 GitHub 项目生成
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 输入
|
||||||
|
./scripts/generate-app.sh https://github.com/alist-org/alist
|
||||||
|
|
||||||
|
# 输出
|
||||||
|
./apps/alist/v3.45.0/
|
||||||
|
├── data.yml
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── logo.png
|
||||||
|
├── README.md
|
||||||
|
└── README_en.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### 生成的 data.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: AList
|
||||||
|
tags:
|
||||||
|
- 实用工具
|
||||||
|
- 云存储
|
||||||
|
title: AList - 文件列表程序
|
||||||
|
description: 支持多存储的文件列表程序和私人网盘
|
||||||
|
additionalProperties:
|
||||||
|
key: alist
|
||||||
|
name: AList
|
||||||
|
tags:
|
||||||
|
- Storage
|
||||||
|
- Tool
|
||||||
|
shortDescZh: 支持多存储的文件列表程序和私人网盘
|
||||||
|
shortDescEn: Supporting multi-storage file listing program
|
||||||
|
website: https://alist.nn.ci/
|
||||||
|
github: https://github.com/alist-org/alist
|
||||||
|
```
|
||||||
|
|
||||||
|
### 生成的 docker-compose.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
alist:
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:5244"
|
||||||
|
volumes:
|
||||||
|
- ./data/data:/opt/alist/data
|
||||||
|
environment:
|
||||||
|
- PUID=0
|
||||||
|
- PGID=0
|
||||||
|
- UMASK=022
|
||||||
|
image: xhofe/alist:v3.45.0
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 示例 2:从 docker run 命令生成
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 输入
|
||||||
|
./scripts/generate-app.sh "docker run -d --name=nginx -p 80:80 nginx:latest"
|
||||||
|
|
||||||
|
# 输出
|
||||||
|
./apps/nginx/latest/
|
||||||
|
├── data.yml
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── logo.png
|
||||||
|
├── README.md
|
||||||
|
└── README_en.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### 生成的 docker-compose.yml
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
nginx:
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:80"
|
||||||
|
volumes:
|
||||||
|
- ./data/data:/app/data
|
||||||
|
environment:
|
||||||
|
- PUID=0
|
||||||
|
- PGID=0
|
||||||
|
- UMASK=022
|
||||||
|
image: nginx:latest
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 示例 3:从 docker-compose 文件链接生成
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 输入
|
||||||
|
./scripts/generate-app.sh https://raw.githubusercontent.com/portainer/portainer/develop/docker-compose.yml
|
||||||
|
|
||||||
|
# 输出
|
||||||
|
./apps/portainer/latest/
|
||||||
|
├── data.yml
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── logo.png
|
||||||
|
├── README.md
|
||||||
|
└── README_en.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 示例 4:从本地文件生成
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 创建测试文件
|
||||||
|
cat > /tmp/test-compose.yml << 'EOF'
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
ports:
|
||||||
|
- "6379:6379"
|
||||||
|
volumes:
|
||||||
|
- redis-data:/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
redis-data:
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 运行脚本
|
||||||
|
./scripts/generate-app.sh /tmp/test-compose.yml ./my-apps
|
||||||
|
|
||||||
|
# 输出
|
||||||
|
./my-apps/redis/7-alpine/
|
||||||
|
├── data.yml
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── logo.png
|
||||||
|
├── README.md
|
||||||
|
└── README_en.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 示例 5:单独下载图标
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 下载 Redis 图标
|
||||||
|
./scripts/download-icon.sh redis ./redis-logo.png 200
|
||||||
|
|
||||||
|
# 输出
|
||||||
|
✓ 从 Simple Icons 下载成功
|
||||||
|
✓ 图标下载完成: ./redis-logo.png
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 示例 6:自定义输出目录
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 输出到指定目录
|
||||||
|
./scripts/generate-app.sh https://github.com/portainer/portainer ~/my-1panel-apps
|
||||||
|
|
||||||
|
# 输出
|
||||||
|
/Users/username/my-1panel-apps/portainer/latest/
|
||||||
|
├── data.yml
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── logo.png
|
||||||
|
├── README.md
|
||||||
|
└── README_en.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 完整工作流程示例
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 生成应用配置
|
||||||
|
./scripts/generate-app.sh https://github.com/alist-org/alist
|
||||||
|
|
||||||
|
# 2. 查看生成的文件
|
||||||
|
cd ./apps/alist/v3.45.0
|
||||||
|
cat data.yml
|
||||||
|
cat docker-compose.yml
|
||||||
|
|
||||||
|
# 3. 手动优化配置
|
||||||
|
# - 补充应用描述
|
||||||
|
# - 添加合适的标签
|
||||||
|
# - 替换 logo.png
|
||||||
|
|
||||||
|
# 4. 测试 docker-compose
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 5. 确认无误后,提交到应用商店
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: add alist app"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 问题:图标下载失败
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 手动下载图标
|
||||||
|
# 访问:https://dashboardicons.com/icons?q=alist
|
||||||
|
# 下载后保存为 logo.png
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题:端口冲突
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 修改 docker-compose.yml 中的端口映射
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:5244" # 修改此处
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题:镜像版本不对
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 手动编辑 docker-compose.yml
|
||||||
|
image: xhofe/alist:v3.45.0 # 修改版本号
|
||||||
|
```
|
||||||
394
skills/references/1panel-examples.md
Normal file
394
skills/references/1panel-examples.md
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
# 1Panel 应用商店参考示例
|
||||||
|
|
||||||
|
本文件包含从 1Panel-Appstore 和 appstore 官方仓库提取的实际应用配置示例。
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
1. [简单单服务应用](#简单单服务应用)
|
||||||
|
2. [带数据库的应用](#带数据库的应用)
|
||||||
|
3. [多端口应用](#多端口应用)
|
||||||
|
4. [多服务应用](#多服务应用)
|
||||||
|
5. [常见标签分类](#常见标签分类)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 简单单服务应用
|
||||||
|
|
||||||
|
### 示例:AList
|
||||||
|
|
||||||
|
**目录结构:**
|
||||||
|
```
|
||||||
|
alist/
|
||||||
|
├── logo.png
|
||||||
|
├── data.yml # 顶层元数据
|
||||||
|
├── README.md
|
||||||
|
├── README_en.md
|
||||||
|
└── 3.45.0/ # 版本目录
|
||||||
|
├── data.yml # 参数定义
|
||||||
|
├── docker-compose.yml
|
||||||
|
└── data/ # 数据目录
|
||||||
|
```
|
||||||
|
|
||||||
|
**顶层 data.yml:**
|
||||||
|
```yaml
|
||||||
|
name: AList
|
||||||
|
tags:
|
||||||
|
- 实用工具
|
||||||
|
- 云存储
|
||||||
|
title: 支持多存储的文件列表程序和私人网盘
|
||||||
|
description: 支持多存储的文件列表程序和私人网盘
|
||||||
|
additionalProperties:
|
||||||
|
key: alist
|
||||||
|
name: AList
|
||||||
|
tags:
|
||||||
|
- Storage
|
||||||
|
- Tool
|
||||||
|
shortDescZh: 支持多存储的文件列表程序和私人网盘
|
||||||
|
shortDescEn: Supporting multi-storage file listing program and private cloud storage
|
||||||
|
description:
|
||||||
|
en: Supporting multi-storage file listing program and private cloud storage
|
||||||
|
ja: 複数ストレージのファイルリスト表示プログラムとプライベートクラウドストレージのサポート
|
||||||
|
ms: Menyokong program senarai fail multi-penyimpanan dan penyimpanan awan peribadi
|
||||||
|
pt-br: Suporte para programa de listagem de arquivos em múltiplos armazenamentos e armazenamento em nuvem privado
|
||||||
|
ru: Поддержка программы отображения файлов в нескольких хранилищах и частного облачного хранилища
|
||||||
|
ko: 다중 저장소 파일 목록 프로그램 및 개인 클라우드 저장소 지원
|
||||||
|
zh-Hant: 支援多存儲檔案列出程序和私人雲端空間
|
||||||
|
zh: 支持多存储文件列出程序和私有云存储
|
||||||
|
type: website
|
||||||
|
crossVersionUpdate: true
|
||||||
|
limit: 0
|
||||||
|
recommend: 65
|
||||||
|
website: https://alist.nn.ci/
|
||||||
|
github: https://github.com/alist-org/alist
|
||||||
|
document: https://alist.nn.ci/zh/guide/
|
||||||
|
architectures:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
- arm/v7
|
||||||
|
- arm/v6
|
||||||
|
- s390x
|
||||||
|
```
|
||||||
|
|
||||||
|
**版本 data.yml(参数定义):**
|
||||||
|
```yaml
|
||||||
|
additionalProperties:
|
||||||
|
formFields:
|
||||||
|
- default: 5244
|
||||||
|
edit: true
|
||||||
|
envKey: PANEL_APP_PORT_HTTP
|
||||||
|
labelEn: WebUI Port
|
||||||
|
labelZh: 网页端口
|
||||||
|
required: true
|
||||||
|
rule: paramPort
|
||||||
|
type: number
|
||||||
|
label:
|
||||||
|
en: WebUI Port
|
||||||
|
ja: WebUI ポート
|
||||||
|
ms: Port WebUI
|
||||||
|
pt-br: Porta WebUI
|
||||||
|
ru: Порт WebUI
|
||||||
|
ko: WebUI 포트
|
||||||
|
zh-Hant: WebUI 埠
|
||||||
|
zh: WebUI 端口
|
||||||
|
- default: 5426
|
||||||
|
edit: true
|
||||||
|
envKey: PANEL_APP_PORT_S3
|
||||||
|
labelEn: S3 Port
|
||||||
|
labelZh: S3 端口
|
||||||
|
required: true
|
||||||
|
rule: paramPort
|
||||||
|
type: number
|
||||||
|
label:
|
||||||
|
en: S3 Port
|
||||||
|
ja: S3 ポート
|
||||||
|
ms: Port S3
|
||||||
|
pt-br: Porta S3
|
||||||
|
ru: Порт S3
|
||||||
|
ko: S3 포트
|
||||||
|
zh-Hant: S3 埠
|
||||||
|
zh: S3 端口
|
||||||
|
```
|
||||||
|
|
||||||
|
**docker-compose.yml:**
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
alist:
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:5244"
|
||||||
|
- "${PANEL_APP_PORT_S3}:5426"
|
||||||
|
volumes:
|
||||||
|
- ./data/data:/opt/alist/data
|
||||||
|
- ./data/mnt:/mnt/data
|
||||||
|
environment:
|
||||||
|
- PUID=0
|
||||||
|
- PGID=0
|
||||||
|
- UMASK=022
|
||||||
|
image: xhofe/alist:v3.45.0
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 带数据库的应用
|
||||||
|
|
||||||
|
### 示例:NocoDB(PostgreSQL)
|
||||||
|
|
||||||
|
**docker-compose.yml:**
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
nocodb:
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:8080"
|
||||||
|
volumes:
|
||||||
|
- ./data/nocodb:/usr/app/data
|
||||||
|
environment:
|
||||||
|
- NC_DB=pg://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}
|
||||||
|
- NC_AUTH_JWT_SECRET=${JWT_SECRET}
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
image: nocodb/nocodb:0.258.2
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
volumes:
|
||||||
|
- ./data/postgres:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
- POSTGRES_DB=${DB_NAME}
|
||||||
|
- POSTGRES_USER=${DB_USER}
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数定义:**
|
||||||
|
```yaml
|
||||||
|
- default: 8080
|
||||||
|
edit: true
|
||||||
|
envKey: PANEL_APP_PORT_HTTP
|
||||||
|
labelEn: Web Port
|
||||||
|
labelZh: Web端口
|
||||||
|
required: true
|
||||||
|
rule: paramPort
|
||||||
|
type: number
|
||||||
|
- default: nocodb
|
||||||
|
edit: true
|
||||||
|
envKey: DB_NAME
|
||||||
|
labelEn: Database Name
|
||||||
|
labelZh: 数据库名称
|
||||||
|
required: true
|
||||||
|
rule: paramCommon
|
||||||
|
type: text
|
||||||
|
- default: nocodb
|
||||||
|
edit: true
|
||||||
|
envKey: DB_USER
|
||||||
|
labelEn: Database User
|
||||||
|
labelZh: 数据库用户
|
||||||
|
required: true
|
||||||
|
rule: paramCommon
|
||||||
|
type: text
|
||||||
|
- default: nocodb_password
|
||||||
|
edit: true
|
||||||
|
envKey: DB_PASSWORD
|
||||||
|
labelEn: Database Password
|
||||||
|
labelZh: 数据库密码
|
||||||
|
required: true
|
||||||
|
rule: paramCommon
|
||||||
|
type: password
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 多端口应用
|
||||||
|
|
||||||
|
### 示例:Nginx Proxy Manager
|
||||||
|
|
||||||
|
**参数定义:**
|
||||||
|
```yaml
|
||||||
|
formFields:
|
||||||
|
- default: 81
|
||||||
|
edit: true
|
||||||
|
envKey: PANEL_APP_PORT_HTTP
|
||||||
|
labelEn: Admin Port
|
||||||
|
labelZh: 管理端口
|
||||||
|
required: true
|
||||||
|
rule: paramPort
|
||||||
|
type: number
|
||||||
|
- default: 80
|
||||||
|
edit: true
|
||||||
|
envKey: PANEL_APP_PORT_NGINX_HTTP
|
||||||
|
labelEn: HTTP Port
|
||||||
|
labelZh: HTTP端口
|
||||||
|
required: true
|
||||||
|
rule: paramPort
|
||||||
|
type: number
|
||||||
|
- default: 443
|
||||||
|
edit: true
|
||||||
|
envKey: PANEL_APP_PORT_NGINX_HTTPS
|
||||||
|
labelEn: HTTPS Port
|
||||||
|
labelZh: HTTPS端口
|
||||||
|
required: true
|
||||||
|
rule: paramPort
|
||||||
|
type: number
|
||||||
|
```
|
||||||
|
|
||||||
|
**docker-compose.yml:**
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:81"
|
||||||
|
- "${PANEL_APP_PORT_NGINX_HTTP}:80"
|
||||||
|
- "${PANEL_APP_PORT_NGINX_HTTPS}:443"
|
||||||
|
volumes:
|
||||||
|
- ./data/data:/data
|
||||||
|
- ./data/letsencrypt:/etc/letsencrypt
|
||||||
|
image: jc21/nginx-proxy-manager:latest
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 多服务应用
|
||||||
|
|
||||||
|
### 示例:Dify(完整栈)
|
||||||
|
|
||||||
|
**docker-compose.yml:**
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
api:
|
||||||
|
container_name: ${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "${PANEL_APP_PORT_HTTP}:80"
|
||||||
|
volumes:
|
||||||
|
- ./data/storage:/app/api/storage
|
||||||
|
environment:
|
||||||
|
- MODE=api
|
||||||
|
- SECRET_KEY=${SECRET_KEY}
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- redis
|
||||||
|
image: langgenius/dify-api:latest
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
worker:
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
environment:
|
||||||
|
- MODE=worker
|
||||||
|
- SECRET_KEY=${SECRET_KEY}
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
- redis
|
||||||
|
image: langgenius/dify-api:latest
|
||||||
|
db:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
volumes:
|
||||||
|
- ./data/postgres:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=${DB_USER}
|
||||||
|
- POSTGRES_PASSWORD=${DB_PASSWORD}
|
||||||
|
- POSTGRES_DB=${DB_NAME}
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
volumes:
|
||||||
|
- ./data/redis:/data
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见标签分类
|
||||||
|
|
||||||
|
### 中文标签(tags)
|
||||||
|
|
||||||
|
| 分类 | 标签 |
|
||||||
|
|------|------|
|
||||||
|
| 开发工具 | 开发工具 |
|
||||||
|
| 实用工具 | 实用工具 |
|
||||||
|
| 文档与笔记 | 文档与笔记 |
|
||||||
|
| 云存储 | 云存储 |
|
||||||
|
| 数据库 | 数据库 |
|
||||||
|
| 监控运维 | 监控运维 |
|
||||||
|
| 安全工具 | 安全工具 |
|
||||||
|
| 网络工具 | 网络工具 |
|
||||||
|
| 建站工具 | 建站工具 |
|
||||||
|
| AI/LLM | AI/LLM |
|
||||||
|
| 容器管理 | 容器管理 |
|
||||||
|
|
||||||
|
### 英文标签(additionalProperties.tags)
|
||||||
|
|
||||||
|
| 分类 | 标签 |
|
||||||
|
|------|------|
|
||||||
|
| 开发工具 | DevTool |
|
||||||
|
| 实用工具 | Utility |
|
||||||
|
| 文档与笔记 | Note |
|
||||||
|
| 云存储 | Storage |
|
||||||
|
| 数据库 | Database |
|
||||||
|
| 监控运维 | Monitor |
|
||||||
|
| 安全工具 | Security |
|
||||||
|
| 网络工具 | Network |
|
||||||
|
| 建站工具 | Website |
|
||||||
|
| AI/LLM | AI |
|
||||||
|
| 容器管理 | Container |
|
||||||
|
|
||||||
|
### 应用类型(type)
|
||||||
|
|
||||||
|
| 类型 | 说明 |
|
||||||
|
|------|------|
|
||||||
|
| website | Web应用(默认) |
|
||||||
|
| runtime | 运行时环境(数据库等) |
|
||||||
|
| tool | 命令行工具 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
1. **版本号**:使用实际的镜像标签版本,如 `v3.45.0`,而非 `latest`
|
||||||
|
2. **推荐值**:优质应用设置 recommend: 60-80,一般应用 30-50
|
||||||
|
3. **架构支持**:至少支持 amd64 和 arm64
|
||||||
|
4. **多语言**:至少提供中英文描述,推荐添加日韩俄等语言
|
||||||
|
5. **数据持久化**:使用 `./data/` 目录,避免绝对路径
|
||||||
|
6. **环境变量**:敏感信息使用 password 类型参数
|
||||||
195
skills/scripts/download-icon.sh
Normal file
195
skills/scripts/download-icon.sh
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Icon Downloader - 从多个图标源下载应用图标
|
||||||
|
# 支持的源:dashboardicons、simpleicons、selfh.st
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# 图标源配置
|
||||||
|
DASHBOARD_ICONS="https://dashboardicons.com/icons"
|
||||||
|
SIMPLE_ICONS="https://cdn.simpleicons.org"
|
||||||
|
SELFHST_ICONS="https://selfh.st/icons"
|
||||||
|
|
||||||
|
# 默认输出尺寸
|
||||||
|
DEFAULT_SIZE=200
|
||||||
|
|
||||||
|
# 打印帮助
|
||||||
|
print_help() {
|
||||||
|
cat << EOF
|
||||||
|
${BLUE}Icon Downloader${NC} - 从多个图标源下载应用图标
|
||||||
|
|
||||||
|
${YELLOW}用法:${NC}
|
||||||
|
$0 <应用名称> [输出文件] [尺寸]
|
||||||
|
|
||||||
|
${YELLOW}参数:${NC}
|
||||||
|
应用名称 - 应用的名称(如 alist, nginx, redis)
|
||||||
|
输出文件 - 图标保存路径(默认: ./logo.png)
|
||||||
|
尺寸 - 图标尺寸(默认: 200x200)
|
||||||
|
|
||||||
|
${YELLOW}图标源优先级:${NC}
|
||||||
|
1. Dashboard Icons (dashboardicons.com)
|
||||||
|
2. Simple Icons (simpleicons.org)
|
||||||
|
3. selfh.st Icons (selfh.st)
|
||||||
|
|
||||||
|
${YELLOW}示例:${NC}
|
||||||
|
$0 alist ./logo.png 200
|
||||||
|
$0 nginx /tmp/nginx-icon.png
|
||||||
|
$0 redis
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# 日志函数
|
||||||
|
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||||
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
|
||||||
|
# 下载并调整图标尺寸
|
||||||
|
download_and_resize() {
|
||||||
|
local url="$1"
|
||||||
|
local output="$2"
|
||||||
|
local size="$3"
|
||||||
|
|
||||||
|
if curl -sSL -o "$output" "$url" 2>/dev/null && [[ -s "$output" ]]; then
|
||||||
|
# 检查是否安装了 ImageMagick 或 sips (macOS)
|
||||||
|
if command -v convert &>/dev/null; then
|
||||||
|
convert "$output" -resize "${size}x${size}" "$output" 2>/dev/null || true
|
||||||
|
elif command -v sips &>/dev/null; then
|
||||||
|
sips -z "$size" "$size" "$output" &>/dev/null || true
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 尝试从各图标源下载
|
||||||
|
try_download_icon() {
|
||||||
|
local app_name="$1"
|
||||||
|
local output="$2"
|
||||||
|
local size="$3"
|
||||||
|
|
||||||
|
local name_lower
|
||||||
|
name_lower=$(echo "$app_name" | tr '[:upper:]' '[:lower:]' | tr -d ' ')
|
||||||
|
|
||||||
|
log_info "尝试下载图标: $app_name"
|
||||||
|
|
||||||
|
# 1. Dashboard Icons
|
||||||
|
log_info "尝试 Dashboard Icons..."
|
||||||
|
local dashboard_url="${DASHBOARD_ICONS}/${name_lower}.png"
|
||||||
|
if download_and_resize "$dashboard_url" "$output" "$size"; then
|
||||||
|
log_info "✓ 从 Dashboard Icons 下载成功"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 尝试带 -dark 后缀
|
||||||
|
if download_and_resize "${DASHBOARD_ICONS}/${name_lower}-dark.png" "$output" "$size"; then
|
||||||
|
log_info "✓ 从 Dashboard Icons (dark) 下载成功"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2. Simple Icons
|
||||||
|
log_info "尝试 Simple Icons..."
|
||||||
|
local simple_url="${SIMPLE_ICONS}/${name_lower}"
|
||||||
|
if download_and_resize "$simple_url" "$output" "$size"; then
|
||||||
|
log_info "✓ 从 Simple Icons 下载成功"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Simple Icons 也支持 SVG
|
||||||
|
if curl -sSL -o "${output%.png}.svg" "${SIMPLE_ICONS}/${name_lower}" 2>/dev/null && [[ -s "${output%.png}.svg" ]]; then
|
||||||
|
log_info "✓ 从 Simple Icons 下载 SVG 成功"
|
||||||
|
# 如果有 SVG,尝试转换
|
||||||
|
if command -v convert &>/dev/null; then
|
||||||
|
convert "${output%.png}.svg" -resize "${size}x${size}" "$output" 2>/dev/null || true
|
||||||
|
if [[ -s "$output" ]]; then
|
||||||
|
rm -f "${output%.png}.svg"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3. selfh.st Icons
|
||||||
|
log_info "尝试 selfh.st Icons..."
|
||||||
|
local selfhst_url="${SELFHST_ICONS}/${name_lower}.png"
|
||||||
|
if download_and_resize "$selfhst_url" "$output" "$size"; then
|
||||||
|
log_info "✓ 从 selfh.st Icons 下载成功"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建占位图标
|
||||||
|
create_placeholder() {
|
||||||
|
local output="$1"
|
||||||
|
local size="$2"
|
||||||
|
|
||||||
|
log_warn "创建占位图标"
|
||||||
|
|
||||||
|
# 使用 ImageMagick 创建简单的占位图标
|
||||||
|
if command -v convert &>/dev/null; then
|
||||||
|
convert -size "${size}x${size}" xc:'#4A90E2' \
|
||||||
|
-gravity center \
|
||||||
|
-pointsize 48 \
|
||||||
|
-fill white \
|
||||||
|
-annotate 0 "?" \
|
||||||
|
"$output" 2>/dev/null
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
# macOS sips 方式
|
||||||
|
if command -v sips &>/dev/null; then
|
||||||
|
# 创建一个简单的 1x1 像素 PNG 然后放大
|
||||||
|
local temp_file="/tmp/placeholder_${RANDOM}.png"
|
||||||
|
echo -n "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" | base64 -d > "$temp_file"
|
||||||
|
sips -z "$size" "$size" "$temp_file" --out "$output" &>/dev/null
|
||||||
|
rm -f "$temp_file"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 最简单的占位符
|
||||||
|
echo -n "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" | base64 -d > "$output"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
local app_name="${1:-}"
|
||||||
|
local output="${2:-./logo.png}"
|
||||||
|
local size="${3:-$DEFAULT_SIZE}"
|
||||||
|
|
||||||
|
# 参数检查
|
||||||
|
if [[ -z "$app_name" ]] || [[ "$app_name" == "-h" ]] || [[ "$app_name" == "--help" ]]; then
|
||||||
|
print_help
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 确保输出目录存在
|
||||||
|
local output_dir
|
||||||
|
output_dir=$(dirname "$output")
|
||||||
|
mkdir -p "$output_dir"
|
||||||
|
|
||||||
|
# 尝试下载
|
||||||
|
if try_download_icon "$app_name" "$output" "$size"; then
|
||||||
|
log_info "${GREEN}✓ 图标下载完成: $output${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 下载失败,创建占位符
|
||||||
|
create_placeholder "$output" "$size"
|
||||||
|
log_warn "未找到图标,已创建占位符: $output"
|
||||||
|
log_info "请手动从以下网站下载合适的图标:"
|
||||||
|
echo " - https://dashboardicons.com/icons?q=${app_name}"
|
||||||
|
echo " - https://simpleicons.org/?q=${app_name}"
|
||||||
|
echo " - https://selfh.st/icons/"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行主函数
|
||||||
|
main "$@"
|
||||||
416
skills/scripts/generate-app.sh
Normal file
416
skills/scripts/generate-app.sh
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# 1Panel App Builder - 主生成脚本
|
||||||
|
# 功能:从 GitHub 项目、docker-compose、docker run 命令生成 1Panel APP 配置
|
||||||
|
# 用法:./generate-app.sh <输入源> [输出目录]
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 默认配置
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
TEMPLATE_DIR="${SCRIPT_DIR}/../templates"
|
||||||
|
OUTPUT_BASE="${2:-./apps}"
|
||||||
|
ICON_SOURCES=(
|
||||||
|
"https://dashboardicons.com/icons"
|
||||||
|
"https://simpleicons.org/icons"
|
||||||
|
"https://selfh.st/icons"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 打印帮助
|
||||||
|
print_help() {
|
||||||
|
cat << EOF
|
||||||
|
${BLUE}1Panel App Builder${NC} - 快速生成 1Panel 应用配置
|
||||||
|
|
||||||
|
${YELLOW}用法:${NC}
|
||||||
|
$0 <输入源> [输出目录]
|
||||||
|
|
||||||
|
${YELLOW}输入源支持:${NC}
|
||||||
|
1. GitHub 项目链接
|
||||||
|
例如: https://github.com/alist-org/alist
|
||||||
|
|
||||||
|
2. docker-compose.yml 文件链接
|
||||||
|
例如: https://raw.githubusercontent.com/alist-org/alist/master/docker-compose.yml
|
||||||
|
|
||||||
|
3. docker run 命令
|
||||||
|
例如: "docker run -d --name=alist -p 5244:5244 xhofe/alist:v3.45.0"
|
||||||
|
|
||||||
|
4. 本地文件路径
|
||||||
|
例如: ./myapp/docker-compose.yml
|
||||||
|
|
||||||
|
${YELLOW}输出:${NC}
|
||||||
|
在指定目录(默认 ./apps)下生成:
|
||||||
|
<app-name>/<version>/
|
||||||
|
├── data.yml # 应用元数据
|
||||||
|
├── docker-compose.yml # 编排文件
|
||||||
|
├── logo.png # 应用图标
|
||||||
|
├── README.md # 中文简介
|
||||||
|
└── README_en.md # 英文简介
|
||||||
|
|
||||||
|
${YELLOW}示例:${NC}
|
||||||
|
$0 https://github.com/alist-org/alist
|
||||||
|
$0 ./my-docker-compose.yml ./my-apps
|
||||||
|
$0 "docker run -d --name nginx -p 80:80 nginx:latest"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# 日志函数
|
||||||
|
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||||
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||||
|
|
||||||
|
# 检测输入类型
|
||||||
|
detect_input_type() {
|
||||||
|
local input="$1"
|
||||||
|
|
||||||
|
# GitHub 项目链接
|
||||||
|
if [[ "$input" =~ ^https?://github\.com/[^/]+/[^/]+ ]]; then
|
||||||
|
echo "github"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# docker-compose 文件链接
|
||||||
|
if [[ "$input" =~ ^https?://.*\.ya?ml$ ]] || [[ "$input" =~ docker-compose ]]; then
|
||||||
|
echo "compose_url"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# docker run 命令
|
||||||
|
if [[ "$input" =~ ^docker\ run ]] || [[ "$input" =~ ^docker\ run$ ]]; then
|
||||||
|
echo "docker_run"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 本地文件
|
||||||
|
if [[ -f "$input" ]]; then
|
||||||
|
if [[ "$input" =~ \.ya?ml$ ]]; then
|
||||||
|
echo "compose_file"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 从 GitHub 项目提取信息
|
||||||
|
extract_from_github() {
|
||||||
|
local github_url="$1"
|
||||||
|
local api_url temp_dir
|
||||||
|
|
||||||
|
log_info "正在从 GitHub 项目提取信息: $github_url"
|
||||||
|
|
||||||
|
# 转换为 API URL
|
||||||
|
# https://github.com/owner/repo -> https://api.github.com/repos/owner/repo
|
||||||
|
api_url="${github_url/github\.com/api.github.com\/repos}"
|
||||||
|
|
||||||
|
# 获取项目信息
|
||||||
|
local repo_info
|
||||||
|
repo_info=$(curl -s "$api_url" 2>/dev/null || echo "{}")
|
||||||
|
|
||||||
|
# 提取字段
|
||||||
|
APP_NAME=$(echo "$repo_info" | jq -r '.name // empty')
|
||||||
|
APP_KEY=$(echo "$APP_NAME" | tr '[:upper:]' '[:lower:]')
|
||||||
|
DESCRIPTION=$(echo "$repo_info" | jq -r '.description // empty')
|
||||||
|
GITHUB="$github_url"
|
||||||
|
WEBSITE=$(echo "$repo_info" | jq -r '.homepage // empty')
|
||||||
|
if [[ -z "$WEBSITE" ]]; then
|
||||||
|
WEBSITE="$github_url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 尝试查找 docker-compose.yml
|
||||||
|
local owner_repo
|
||||||
|
owner_repo=$(echo "$github_url" | sed -E 's|https?://github.com/||')
|
||||||
|
COMPOSE_URL="https://raw.githubusercontent.com/${owner_repo}/main/docker-compose.yml"
|
||||||
|
|
||||||
|
log_info "应用名称: $APP_NAME"
|
||||||
|
log_info "描述: $DESCRIPTION"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 从 docker-compose 提取信息
|
||||||
|
extract_from_compose() {
|
||||||
|
local compose_content="$1"
|
||||||
|
|
||||||
|
log_info "正在解析 docker-compose 内容"
|
||||||
|
|
||||||
|
# 提取服务名
|
||||||
|
SERVICE_NAME=$(echo "$compose_content" | yq '.services | keys | .[0]' 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
# 提取镜像
|
||||||
|
local image
|
||||||
|
image=$(echo "$compose_content" | yq ".services.${SERVICE_NAME}.image" 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
# 解析镜像名和标签
|
||||||
|
if [[ "$image" =~ ^([^:]+):(.+)$ ]]; then
|
||||||
|
IMAGE="${BASH_REMATCH[1]}"
|
||||||
|
TAG="${BASH_REMATCH[2]}"
|
||||||
|
else
|
||||||
|
IMAGE="$image"
|
||||||
|
TAG="latest"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 提取端口
|
||||||
|
PORT=$(echo "$compose_content" | yq ".services.${SERVICE_NAME}.ports[0]" 2>/dev/null | grep -oE '[0-9]+$' || echo "8080")
|
||||||
|
|
||||||
|
log_info "服务名: $SERVICE_NAME"
|
||||||
|
log_info "镜像: $IMAGE:$TAG"
|
||||||
|
log_info "端口: $PORT"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 从 docker run 命令提取信息
|
||||||
|
extract_from_docker_run() {
|
||||||
|
local cmd="$1"
|
||||||
|
|
||||||
|
log_info "正在解析 docker run 命令"
|
||||||
|
|
||||||
|
# 提取镜像
|
||||||
|
IMAGE=$(echo "$cmd" | grep -oE '[^ ]+:[^ ]+$' | cut -d':' -f1 || echo "")
|
||||||
|
TAG=$(echo "$cmd" | grep -oE '[^ ]+:[^ ]+$' | cut -d':' -f2 || echo "latest")
|
||||||
|
|
||||||
|
# 提取容器名
|
||||||
|
SERVICE_NAME=$(echo "$cmd" | grep -oE '\-\-name[= ]+[^ ]+' | awk '{print $NF}' || echo "app")
|
||||||
|
|
||||||
|
# 提取端口
|
||||||
|
PORT=$(echo "$cmd" | grep -oE '\-p[= ]+[0-9]+:[0-9]+' | grep -oE '[0-9]+$' || echo "8080")
|
||||||
|
|
||||||
|
APP_NAME="$SERVICE_NAME"
|
||||||
|
APP_KEY=$(echo "$SERVICE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
|
log_info "应用名称: $APP_NAME"
|
||||||
|
log_info "镜像: $IMAGE:$TAG"
|
||||||
|
log_info "端口: $PORT"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 生成 data.yml
|
||||||
|
generate_data_yml() {
|
||||||
|
local output_file="$1"
|
||||||
|
|
||||||
|
log_info "生成 data.yml: $output_file"
|
||||||
|
|
||||||
|
cat > "$output_file" << EOF
|
||||||
|
name: ${APP_NAME:-MyApp}
|
||||||
|
tags:
|
||||||
|
- 实用工具
|
||||||
|
- 容器
|
||||||
|
title: ${APP_NAME:-MyApp} - 容器应用
|
||||||
|
description: ${DESCRIPTION:-自动生成的应用配置}
|
||||||
|
additionalProperties:
|
||||||
|
key: ${APP_KEY:-myapp}
|
||||||
|
name: ${APP_NAME:-MyApp}
|
||||||
|
tags:
|
||||||
|
- Tool
|
||||||
|
- Container
|
||||||
|
shortDescZh: ${DESCRIPTION:-自动生成的应用配置}
|
||||||
|
shortDescEn: ${DESCRIPTION:-Auto-generated application configuration}
|
||||||
|
description:
|
||||||
|
en: ${DESCRIPTION:-Auto-generated application configuration}
|
||||||
|
ja: ${DESCRIPTION:-Auto-generated application configuration}
|
||||||
|
ms: ${DESCRIPTION:-Auto-generated application configuration}
|
||||||
|
pt-br: ${DESCRIPTION:-Auto-generated application configuration}
|
||||||
|
ru: ${DESCRIPTION:-Auto-generated application configuration}
|
||||||
|
ko: ${DESCRIPTION:-Auto-generated application configuration}
|
||||||
|
zh-Hant: ${DESCRIPTION:-Auto-generated application configuration}
|
||||||
|
zh: ${DESCRIPTION:-自动生成的应用配置}
|
||||||
|
type: website
|
||||||
|
crossVersionUpdate: true
|
||||||
|
limit: 0
|
||||||
|
recommend: 50
|
||||||
|
website: ${WEBSITE:-https://example.com}
|
||||||
|
github: ${GITHUB:-https://github.com}
|
||||||
|
document: ${GITHUB:-https://github.com}
|
||||||
|
architectures:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# 生成 docker-compose.yml
|
||||||
|
generate_docker_compose() {
|
||||||
|
local output_file="$1"
|
||||||
|
|
||||||
|
log_info "生成 docker-compose.yml: $output_file"
|
||||||
|
|
||||||
|
cat > "$output_file" << EOF
|
||||||
|
services:
|
||||||
|
${SERVICE_NAME:-app}:
|
||||||
|
container_name: \${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "\${PANEL_APP_PORT_HTTP}:${PORT:-8080}"
|
||||||
|
volumes:
|
||||||
|
- ./data/data:/app/data
|
||||||
|
environment:
|
||||||
|
- PUID=0
|
||||||
|
- PGID=0
|
||||||
|
- UMASK=022
|
||||||
|
image: ${IMAGE:-app}:${TAG:-latest}
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# 生成 README
|
||||||
|
generate_readme() {
|
||||||
|
local output_dir="$1"
|
||||||
|
|
||||||
|
log_info "生成 README 文件"
|
||||||
|
|
||||||
|
cat > "${output_dir}/README.md" << EOF
|
||||||
|
# ${APP_NAME:-MyApp}
|
||||||
|
|
||||||
|
## 简介
|
||||||
|
|
||||||
|
${DESCRIPTION:-这是一个自动生成的应用配置。}
|
||||||
|
|
||||||
|
## 使用说明
|
||||||
|
|
||||||
|
1. 在 1Panel 应用商店中安装此应用
|
||||||
|
2. 配置相关参数
|
||||||
|
3. 启动应用
|
||||||
|
|
||||||
|
## 更多信息
|
||||||
|
|
||||||
|
- 官网: ${WEBSITE:-https://example.com}
|
||||||
|
- GitHub: ${GITHUB:-https://github.com}
|
||||||
|
- 文档: ${GITHUB:-https://github.com}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat > "${output_dir}/README_en.md" << EOF
|
||||||
|
# ${APP_NAME:-MyApp}
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
${DESCRIPTION:-This is an auto-generated application configuration.}
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Install this app from 1Panel App Store
|
||||||
|
2. Configure parameters
|
||||||
|
3. Start the application
|
||||||
|
|
||||||
|
## More Information
|
||||||
|
|
||||||
|
- Website: ${WEBSITE:-https://example.com}
|
||||||
|
- GitHub: ${GITHUB:-https://github.com}
|
||||||
|
- Documentation: ${GITHUB:-https://github.com}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# 下载图标
|
||||||
|
download_icon() {
|
||||||
|
local app_name="$1"
|
||||||
|
local output_file="$2"
|
||||||
|
local icon_name
|
||||||
|
|
||||||
|
icon_name=$(echo "$app_name" | tr '[:upper:]' '[:lower:]')
|
||||||
|
|
||||||
|
log_info "尝试下载图标: $app_name"
|
||||||
|
|
||||||
|
# 尝试各个图标源
|
||||||
|
for source in "${ICON_SOURCES[@]}"; do
|
||||||
|
local icon_url="${source}/${icon_name}.png"
|
||||||
|
if curl -sSL -o "$output_file" "$icon_url" 2>/dev/null && [[ -s "$output_file" ]]; then
|
||||||
|
log_info "图标下载成功: $icon_url"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log_warn "未找到图标,使用占位符"
|
||||||
|
# 创建简单的占位图标(1x1 像素 PNG)
|
||||||
|
echo -n "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" | base64 -d > "$output_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
local input="$1"
|
||||||
|
local input_type
|
||||||
|
|
||||||
|
# 参数检查
|
||||||
|
if [[ -z "$input" ]] || [[ "$input" == "-h" ]] || [[ "$input" == "--help" ]]; then
|
||||||
|
print_help
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "开始处理: $input"
|
||||||
|
|
||||||
|
# 检测输入类型
|
||||||
|
input_type=$(detect_input_type "$input")
|
||||||
|
log_info "检测到输入类型: $input_type"
|
||||||
|
|
||||||
|
# 根据类型提取信息
|
||||||
|
case "$input_type" in
|
||||||
|
github)
|
||||||
|
extract_from_github "$input"
|
||||||
|
COMPOSE_CONTENT=$(curl -s "$COMPOSE_URL" 2>/dev/null || echo "")
|
||||||
|
if [[ -n "$COMPOSE_CONTENT" ]]; then
|
||||||
|
extract_from_compose "$COMPOSE_CONTENT"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
compose_url)
|
||||||
|
COMPOSE_CONTENT=$(curl -s "$input" 2>/dev/null)
|
||||||
|
extract_from_compose "$COMPOSE_CONTENT"
|
||||||
|
APP_NAME="$SERVICE_NAME"
|
||||||
|
APP_KEY=$(echo "$SERVICE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||||
|
;;
|
||||||
|
compose_file)
|
||||||
|
COMPOSE_CONTENT=$(cat "$input")
|
||||||
|
extract_from_compose "$COMPOSE_CONTENT"
|
||||||
|
APP_NAME="$SERVICE_NAME"
|
||||||
|
APP_KEY=$(echo "$SERVICE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||||
|
;;
|
||||||
|
docker_run)
|
||||||
|
extract_from_docker_run "$input"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log_error "无法识别的输入类型: $input"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# 创建输出目录
|
||||||
|
local output_dir="${OUTPUT_BASE}/${APP_KEY}/${TAG:-latest}"
|
||||||
|
mkdir -p "$output_dir"
|
||||||
|
|
||||||
|
log_info "输出目录: $output_dir"
|
||||||
|
|
||||||
|
# 生成文件
|
||||||
|
generate_data_yml "${output_dir}/data.yml"
|
||||||
|
generate_docker_compose "${output_dir}/docker-compose.yml"
|
||||||
|
generate_readme "$output_dir"
|
||||||
|
download_icon "$APP_NAME" "${output_dir}/logo.png"
|
||||||
|
|
||||||
|
# 生成上级目录的 data.yml
|
||||||
|
generate_data_yml "${OUTPUT_BASE}/${APP_KEY}/data.yml"
|
||||||
|
cp "${output_dir}/logo.png" "${OUTPUT_BASE}/${APP_KEY}/logo.png" 2>/dev/null || true
|
||||||
|
cp "${output_dir}/README.md" "${OUTPUT_BASE}/${APP_KEY}/README.md" 2>/dev/null || true
|
||||||
|
cp "${output_dir}/README_en.md" "${OUTPUT_BASE}/${APP_KEY}/README_en.md" 2>/dev/null || true
|
||||||
|
|
||||||
|
# 输出结果
|
||||||
|
echo ""
|
||||||
|
log_info "${GREEN}✓ 生成完成!${NC}"
|
||||||
|
echo ""
|
||||||
|
echo "目录结构:"
|
||||||
|
tree "${OUTPUT_BASE}/${APP_KEY}" 2>/dev/null || find "${OUTPUT_BASE}/${APP_KEY}" -type f
|
||||||
|
echo ""
|
||||||
|
log_info "下一步:"
|
||||||
|
echo " 1. 检查生成的配置文件"
|
||||||
|
echo " 2. 补充完善应用描述和标签"
|
||||||
|
echo " 3. 替换 logo.png 为合适的应用图标"
|
||||||
|
echo " 4. 测试 docker-compose.yml"
|
||||||
|
echo " 5. 提交到应用商店仓库"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行主函数
|
||||||
|
main "$@"
|
||||||
257
skills/scripts/validate-app.sh
Normal file
257
skills/scripts/validate-app.sh
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# 1Panel App Validator - 验证生成的配置是否符合规范
|
||||||
|
# 用法:./validate-app.sh <app-directory>
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
# 计数器
|
||||||
|
ERRORS=0
|
||||||
|
WARNINGS=0
|
||||||
|
|
||||||
|
# 打印帮助
|
||||||
|
print_help() {
|
||||||
|
cat << EOF
|
||||||
|
${BLUE}1Panel App Validator${NC} - 验证应用配置是否符合规范
|
||||||
|
|
||||||
|
${YELLOW}用法:${NC}
|
||||||
|
$0 <app-directory>
|
||||||
|
|
||||||
|
${YELLOW}检查项目:${NC}
|
||||||
|
- 目录结构完整性
|
||||||
|
- data.yml 格式正确性
|
||||||
|
- docker-compose.yml 变量使用
|
||||||
|
- logo.png 是否存在
|
||||||
|
- README 文件是否存在
|
||||||
|
|
||||||
|
${YELLOW}示例:${NC}
|
||||||
|
$0 ./apps/alist
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# 日志函数
|
||||||
|
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||||
|
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; ((WARNINGS++)); }
|
||||||
|
log_error() { echo -e "${RED}[ERROR]${NC} $1"; ((ERRORS++)); }
|
||||||
|
|
||||||
|
# 检查目录结构
|
||||||
|
check_directory_structure() {
|
||||||
|
local app_dir="$1"
|
||||||
|
local app_name
|
||||||
|
app_name=$(basename "$app_dir")
|
||||||
|
|
||||||
|
log_info "检查目录结构: $app_name"
|
||||||
|
|
||||||
|
# 检查必需文件
|
||||||
|
if [[ ! -f "$app_dir/data.yml" ]]; then
|
||||||
|
log_error "缺少顶层 data.yml"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$app_dir/logo.png" ]]; then
|
||||||
|
log_error "缺少 logo.png"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$app_dir/README.md" ]]; then
|
||||||
|
log_warn "缺少 README.md(推荐)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 查找版本目录
|
||||||
|
local version_dirs
|
||||||
|
version_dirs=$(find "$app_dir" -maxdepth 1 -type d -name "v*" -o -name "latest" -o -name "[0-9]*" 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
if [[ -z "$version_dirs" ]]; then
|
||||||
|
log_error "未找到版本目录(如 1.0.0/, v1.0.0/, latest/)"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查每个版本目录
|
||||||
|
for version_dir in $version_dirs; do
|
||||||
|
log_info "检查版本目录: $(basename "$version_dir")"
|
||||||
|
|
||||||
|
if [[ ! -f "$version_dir/data.yml" ]]; then
|
||||||
|
log_error "版本目录缺少 data.yml: $version_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$version_dir/docker-compose.yml" ]]; then
|
||||||
|
log_error "版本目录缺少 docker-compose.yml: $version_dir"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# 验证顶层 data.yml
|
||||||
|
validate_top_data_yml() {
|
||||||
|
local data_file="$1"
|
||||||
|
|
||||||
|
log_info "验证顶层 data.yml"
|
||||||
|
|
||||||
|
if [[ ! -f "$data_file" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查必需字段
|
||||||
|
local required_fields=("name" "title" "description")
|
||||||
|
for field in "${required_fields[@]}"; do
|
||||||
|
if ! grep -q "^${field}:" "$data_file"; then
|
||||||
|
log_error "data.yml 缺少必需字段: $field"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# 检查 additionalProperties
|
||||||
|
if ! grep -q "additionalProperties:" "$data_file"; then
|
||||||
|
log_error "data.yml 缺少 additionalProperties"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 key
|
||||||
|
if ! grep -q "key:" "$data_file"; then
|
||||||
|
log_error "data.yml 缺少 additionalProperties.key"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 tags
|
||||||
|
if ! grep -q "tags:" "$data_file"; then
|
||||||
|
log_warn "data.yml 缺少 tags(推荐)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 architectures
|
||||||
|
if ! grep -q "architectures:" "$data_file"; then
|
||||||
|
log_warn "data.yml 缺少 architectures(推荐)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 验证版本 data.yml
|
||||||
|
validate_version_data_yml() {
|
||||||
|
local data_file="$1"
|
||||||
|
|
||||||
|
log_info "验证版本 data.yml"
|
||||||
|
|
||||||
|
if [[ ! -f "$data_file" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 formFields
|
||||||
|
if ! grep -q "formFields:" "$data_file"; then
|
||||||
|
log_warn "版本 data.yml 缺少 formFields(如果无可配置参数则忽略)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查每个参数是否有 envKey
|
||||||
|
local param_count
|
||||||
|
param_count=$(grep -c "envKey:" "$data_file" 2>/dev/null || echo "0")
|
||||||
|
|
||||||
|
if [[ "$param_count" -eq 0 ]]; then
|
||||||
|
log_warn "formFields 中未找到 envKey 定义"
|
||||||
|
else
|
||||||
|
log_info "找到 $param_count 个可配置参数"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 验证 docker-compose.yml
|
||||||
|
validate_docker_compose() {
|
||||||
|
local compose_file="$1"
|
||||||
|
|
||||||
|
log_info "验证 docker-compose.yml"
|
||||||
|
|
||||||
|
if [[ ! -f "$compose_file" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 container_name 使用变量
|
||||||
|
if grep -q "container_name:" "$compose_file"; then
|
||||||
|
if ! grep -q 'container_name:.*\${CONTAINER_NAME}' "$compose_file"; then
|
||||||
|
log_error "container_name 必须使用 \${CONTAINER_NAME} 变量"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 networks
|
||||||
|
if ! grep -q "1panel-network:" "$compose_file"; then
|
||||||
|
log_error "docker-compose.yml 缺少 1panel-network"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! grep -q "external: true" "$compose_file"; then
|
||||||
|
log_error "1panel-network 必须设置为 external: true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 restart
|
||||||
|
if ! grep -q "restart: always" "$compose_file"; then
|
||||||
|
log_warn "建议设置 restart: always"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查 labels
|
||||||
|
if ! grep -q 'createdBy: "Apps"' "$compose_file"; then
|
||||||
|
log_warn "建议添加 labels: createdBy: \"Apps\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查端口映射使用变量
|
||||||
|
if grep -q "ports:" "$compose_file"; then
|
||||||
|
if ! grep -q 'PANEL_APP_PORT_' "$compose_file"; then
|
||||||
|
log_warn "端口映射建议使用 PANEL_APP_PORT_* 变量"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查数据卷路径
|
||||||
|
if grep -q "volumes:" "$compose_file"; then
|
||||||
|
if grep -qE '^\s+- /[a-zA-Z]' "$compose_file"; then
|
||||||
|
log_warn "检测到绝对路径的数据卷,建议使用 ./data/ 相对路径"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
local app_dir="${1:-}"
|
||||||
|
|
||||||
|
# 参数检查
|
||||||
|
if [[ -z "$app_dir" ]] || [[ "$app_dir" == "-h" ]] || [[ "$app_dir" == "--help" ]]; then
|
||||||
|
print_help
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "$app_dir" ]]; then
|
||||||
|
log_error "目录不存在: $app_dir"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== 1Panel App Validator ===${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# 执行检查
|
||||||
|
check_directory_structure "$app_dir"
|
||||||
|
validate_top_data_yml "$app_dir/data.yml"
|
||||||
|
|
||||||
|
# 查找并验证版本目录
|
||||||
|
local version_dirs
|
||||||
|
version_dirs=$(find "$app_dir" -maxdepth 1 -type d \( -name "v*" -o -name "latest" -o -name "[0-9]*" \) 2>/dev/null || echo "")
|
||||||
|
|
||||||
|
for version_dir in $version_dirs; do
|
||||||
|
validate_version_data_yml "$version_dir/data.yml"
|
||||||
|
validate_docker_compose "$version_dir/docker-compose.yml"
|
||||||
|
done
|
||||||
|
|
||||||
|
# 输出结果
|
||||||
|
echo ""
|
||||||
|
echo -e "${BLUE}=== 验证结果 ===${NC}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ $ERRORS -eq 0 ]] && [[ $WARNINGS -eq 0 ]]; then
|
||||||
|
echo -e "${GREEN}✓ 验证通过!未发现问题。${NC}"
|
||||||
|
exit 0
|
||||||
|
elif [[ $ERRORS -eq 0 ]]; then
|
||||||
|
echo -e "${YELLOW}⚠ 验证通过,但有 $WARNINGS 个警告。${NC}"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ 验证失败!发现 $ERRORS 个错误和 $WARNINGS 个警告。${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行主函数
|
||||||
|
main "$@"
|
||||||
33
skills/templates/data.yml.tpl
Normal file
33
skills/templates/data.yml.tpl
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: ${APP_NAME}
|
||||||
|
tags:
|
||||||
|
- ${TAG_1}
|
||||||
|
- ${TAG_2}
|
||||||
|
title: ${TITLE_ZH}
|
||||||
|
description: ${DESC_ZH}
|
||||||
|
additionalProperties:
|
||||||
|
key: ${APP_KEY}
|
||||||
|
name: ${APP_NAME}
|
||||||
|
tags:
|
||||||
|
- ${TAG_EN_1}
|
||||||
|
- ${TAG_EN_2}
|
||||||
|
shortDescZh: ${SHORT_DESC_ZH}
|
||||||
|
shortDescEn: ${SHORT_DESC_EN}
|
||||||
|
description:
|
||||||
|
en: ${DESC_EN}
|
||||||
|
ja: ${DESC_JA:-Supporting multi-storage file listing program and private cloud storage}
|
||||||
|
ms: ${DESC_MS:-Supporting multi-storage file listing program and private cloud storage}
|
||||||
|
pt-br: ${DESC_PT_BR:-Supporting multi-storage file listing program and private cloud storage}
|
||||||
|
ru: ${DESC_RU:-Supporting multi-storage file listing program and private cloud storage}
|
||||||
|
ko: ${DESC_KO:-Supporting multi-storage file listing program and private cloud storage}
|
||||||
|
zh-Hant: ${DESC_ZH_HANT:-支援多存儲檔案列出程序和私人雲端空間}
|
||||||
|
zh: ${DESC_ZH}
|
||||||
|
type: ${APP_TYPE}
|
||||||
|
crossVersionUpdate: ${CROSS_VERSION_UPDATE:-true}
|
||||||
|
limit: ${LIMIT:-0}
|
||||||
|
recommend: ${RECOMMEND:-50}
|
||||||
|
website: ${WEBSITE}
|
||||||
|
github: ${GITHUB}
|
||||||
|
document: ${DOCUMENT:-}
|
||||||
|
architectures:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
20
skills/templates/docker-compose.yml.tpl
Normal file
20
skills/templates/docker-compose.yml.tpl
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
services:
|
||||||
|
${SERVICE_NAME}:
|
||||||
|
container_name: \${CONTAINER_NAME}
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
- 1panel-network
|
||||||
|
ports:
|
||||||
|
- "\${PANEL_APP_PORT_HTTP}:${PORT}"
|
||||||
|
volumes:
|
||||||
|
- ./data/data:/app/data
|
||||||
|
environment:
|
||||||
|
- PUID=0
|
||||||
|
- PGID=0
|
||||||
|
- UMASK=022
|
||||||
|
image: ${IMAGE}:${TAG}
|
||||||
|
labels:
|
||||||
|
createdBy: "Apps"
|
||||||
|
networks:
|
||||||
|
1panel-network:
|
||||||
|
external: true
|
||||||
Reference in New Issue
Block a user