Spaces:
Paused
Paused
Upload 21 files
Browse files- Dockerfile +6 -32
- app/main.py +3 -64
- entrypoint.sh +5 -23
Dockerfile
CHANGED
|
@@ -4,25 +4,6 @@ FROM python:3.9-alpine
|
|
| 4 |
# 设置工作目录
|
| 5 |
WORKDIR /app
|
| 6 |
|
| 7 |
-
# 添加一个随机标签,强制破坏缓存
|
| 8 |
-
LABEL rebuild=$(date +%s)
|
| 9 |
-
|
| 10 |
-
# 创建data目录
|
| 11 |
-
RUN mkdir -p ./data
|
| 12 |
-
|
| 13 |
-
# 立即复制数据目录 - 这是最优先的
|
| 14 |
-
COPY data/ ./data/
|
| 15 |
-
# 添加验证命令
|
| 16 |
-
RUN echo "=== CHECKING CONFIG FILES IN /app/data ===" && \
|
| 17 |
-
ls -la ./data && \
|
| 18 |
-
if [ -f "./data/config.yaml" ]; then \
|
| 19 |
-
echo "CONFIG FILE FOUND AND COPIED SUCCESSFULLY!"; \
|
| 20 |
-
head -n 5 ./data/config.yaml; \
|
| 21 |
-
else \
|
| 22 |
-
echo "ERROR: CONFIG FILE NOT FOUND!"; \
|
| 23 |
-
exit 1; \
|
| 24 |
-
fi
|
| 25 |
-
|
| 26 |
# 安装系统依赖
|
| 27 |
# 添加 yaml-dev 提供编译PyYAML所需的libyaml
|
| 28 |
# 添加 unzip 用于解压 Yacd
|
|
@@ -47,8 +28,8 @@ RUN apk add --no-cache \
|
|
| 47 |
# 设置时区为亚洲/上海
|
| 48 |
ENV TZ=Asia/Shanghai
|
| 49 |
|
| 50 |
-
# 创建必要的目录并设置权限
|
| 51 |
-
RUN mkdir -p ./clash_core ./subconverter && \
|
| 52 |
chmod -R 777 ./data && \
|
| 53 |
chmod -R 777 ./clash_core && \
|
| 54 |
chmod -R 777 ./subconverter
|
|
@@ -129,8 +110,7 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
|
|
| 129 |
FLASK_PORT=7860 \
|
| 130 |
CLASH_PROXY_PORT=7890 \
|
| 131 |
CLASH_API_PORT=9090 \
|
| 132 |
-
PORT=7860
|
| 133 |
-
USE_LOCAL_CONFIG=true
|
| 134 |
|
| 135 |
# 复制应用代码和静态文件
|
| 136 |
COPY app/ ./app/
|
|
@@ -139,15 +119,9 @@ COPY app/ ./app/
|
|
| 139 |
COPY entrypoint.sh ./
|
| 140 |
RUN chmod +x ./entrypoint.sh
|
| 141 |
|
| 142 |
-
#
|
| 143 |
-
RUN
|
| 144 |
-
|
| 145 |
-
if [ -f "./data/config.yaml" ]; then \
|
| 146 |
-
echo "CONFIG FILE STILL EXISTS - GOOD!"; \
|
| 147 |
-
else \
|
| 148 |
-
echo "ERROR: CONFIG FILE MISSING AFTER APP COPY!"; \
|
| 149 |
-
exit 1; \
|
| 150 |
-
fi
|
| 151 |
|
| 152 |
# 暴露端口
|
| 153 |
EXPOSE $FLASK_PORT $CLASH_PROXY_PORT $CLASH_API_PORT
|
|
|
|
| 4 |
# 设置工作目录
|
| 5 |
WORKDIR /app
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
# 安装系统依赖
|
| 8 |
# 添加 yaml-dev 提供编译PyYAML所需的libyaml
|
| 9 |
# 添加 unzip 用于解压 Yacd
|
|
|
|
| 28 |
# 设置时区为亚洲/上海
|
| 29 |
ENV TZ=Asia/Shanghai
|
| 30 |
|
| 31 |
+
# 创建必要的目录并设置权限(构建阶段就设置好权限)
|
| 32 |
+
RUN mkdir -p ./clash_core ./subconverter ./data && \
|
| 33 |
chmod -R 777 ./data && \
|
| 34 |
chmod -R 777 ./clash_core && \
|
| 35 |
chmod -R 777 ./subconverter
|
|
|
|
| 110 |
FLASK_PORT=7860 \
|
| 111 |
CLASH_PROXY_PORT=7890 \
|
| 112 |
CLASH_API_PORT=9090 \
|
| 113 |
+
PORT=7860
|
|
|
|
| 114 |
|
| 115 |
# 复制应用代码和静态文件
|
| 116 |
COPY app/ ./app/
|
|
|
|
| 119 |
COPY entrypoint.sh ./
|
| 120 |
RUN chmod +x ./entrypoint.sh
|
| 121 |
|
| 122 |
+
# 给脚本和二进制文件执行权限 (重复的chmod可能不需要,但在构建阶段设置更安全)
|
| 123 |
+
RUN chmod +x ./clash_core/clash.meta-linux-amd64 || true
|
| 124 |
+
RUN chmod +x ./subconverter/subconverter || true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
# 暴露端口
|
| 127 |
EXPOSE $FLASK_PORT $CLASH_PROXY_PORT $CLASH_API_PORT
|
app/main.py
CHANGED
|
@@ -39,39 +39,16 @@ initialization_error = None
|
|
| 39 |
@app.before_request
|
| 40 |
def initialize_once():
|
| 41 |
"""应用首次请求前的初始化"""
|
| 42 |
-
global clash_manager, sub_manager, initialization_error
|
| 43 |
|
| 44 |
# 使用类变量确保只初始化一次
|
| 45 |
if not getattr(initialize_once, '_initialized', False):
|
| 46 |
logger.info("正在初始化应用 (首次请求)...")
|
| 47 |
|
| 48 |
-
config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "config.yaml")
|
| 49 |
-
|
| 50 |
-
# 首先检查是否存在有效的本地配置文件
|
| 51 |
-
if os.path.exists(config_path) and os.path.getsize(config_path) > 0:
|
| 52 |
-
logger.info("检测到有效的本地配置文件,直接使用它启动Clash")
|
| 53 |
-
try:
|
| 54 |
-
# 初始化Clash管理器并使用本地配置文件
|
| 55 |
-
clash_manager = ClashManager(
|
| 56 |
-
config_path=config_path,
|
| 57 |
-
clash_path=os.path.join(os.path.dirname(os.path.dirname(__file__)), "clash_core", "clash.meta-linux-amd64"),
|
| 58 |
-
api_port=CLASH_API_PORT,
|
| 59 |
-
proxy_port=CLASH_PROXY_PORT
|
| 60 |
-
)
|
| 61 |
-
|
| 62 |
-
# 启动Clash Core
|
| 63 |
-
clash_manager.start_clash()
|
| 64 |
-
logger.info("成功使用本地配置文件启动Clash Core")
|
| 65 |
-
initialize_once._initialized = True
|
| 66 |
-
return
|
| 67 |
-
except Exception as e:
|
| 68 |
-
logger.warning(f"使用本地配置文件启动失败,将尝试从订阅加载: {str(e)}")
|
| 69 |
-
# 继续尝试从订阅加载
|
| 70 |
-
|
| 71 |
# 初始化订阅管理器
|
| 72 |
sub_manager = SubscriptionManager(
|
| 73 |
sub_url=SUB_URL,
|
| 74 |
-
config_path=
|
| 75 |
)
|
| 76 |
|
| 77 |
# 加载订阅并转换为Clash配置
|
|
@@ -87,7 +64,7 @@ def initialize_once():
|
|
| 87 |
|
| 88 |
# 初始化Clash管理器
|
| 89 |
clash_manager = ClashManager(
|
| 90 |
-
config_path=
|
| 91 |
clash_path=os.path.join(os.path.dirname(os.path.dirname(__file__)), "clash_core", "clash.meta-linux-amd64"),
|
| 92 |
api_port=CLASH_API_PORT,
|
| 93 |
proxy_port=CLASH_PROXY_PORT
|
|
@@ -475,44 +452,6 @@ def index():
|
|
| 475 |
</html>
|
| 476 |
"""
|
| 477 |
|
| 478 |
-
@app.route("/api/use_local_config", methods=["POST"])
|
| 479 |
-
@authenticate
|
| 480 |
-
def use_local_config():
|
| 481 |
-
"""直接使用本地的config.yaml文件,跳过订阅转换"""
|
| 482 |
-
global clash_manager, sub_manager, initialization_error
|
| 483 |
-
|
| 484 |
-
try:
|
| 485 |
-
config_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "config.yaml")
|
| 486 |
-
|
| 487 |
-
# 检查文件是否存在
|
| 488 |
-
if not os.path.exists(config_path):
|
| 489 |
-
return jsonify({"success": False, "error": "本地配置文件不存在"}), 404
|
| 490 |
-
|
| 491 |
-
# 停止当前的Clash服务(如果正在运行)
|
| 492 |
-
if clash_manager is not None:
|
| 493 |
-
clash_manager.stop_clash()
|
| 494 |
-
|
| 495 |
-
# 重新初始化Clash管理器并使用本地配置文件启动
|
| 496 |
-
clash_manager = ClashManager(
|
| 497 |
-
config_path=config_path,
|
| 498 |
-
clash_path=os.path.join(os.path.dirname(os.path.dirname(__file__)), "clash_core", "clash.meta-linux-amd64"),
|
| 499 |
-
api_port=CLASH_API_PORT,
|
| 500 |
-
proxy_port=CLASH_PROXY_PORT
|
| 501 |
-
)
|
| 502 |
-
|
| 503 |
-
# 启动Clash Core
|
| 504 |
-
clash_manager.start_clash()
|
| 505 |
-
initialization_error = None
|
| 506 |
-
|
| 507 |
-
logger.info("成功使用本地配置文件启动Clash Core")
|
| 508 |
-
return jsonify({"success": True, "message": "已使用本地配置文件启动服务"})
|
| 509 |
-
|
| 510 |
-
except Exception as e:
|
| 511 |
-
error_msg = f"使用本地配置文件失败: {str(e)}"
|
| 512 |
-
logger.error(error_msg)
|
| 513 |
-
initialization_error = error_msg
|
| 514 |
-
return jsonify({"success": False, "error": error_msg}), 500
|
| 515 |
-
|
| 516 |
if __name__ == "__main__":
|
| 517 |
# 如果直接运行此文件,将初始化应用并启动Flask服务器
|
| 518 |
initialize_once()
|
|
|
|
| 39 |
@app.before_request
|
| 40 |
def initialize_once():
|
| 41 |
"""应用首次请求前的初始化"""
|
| 42 |
+
global clash_manager, sub_manager, initialization_error, _initialized
|
| 43 |
|
| 44 |
# 使用类变量确保只初始化一次
|
| 45 |
if not getattr(initialize_once, '_initialized', False):
|
| 46 |
logger.info("正在初始化应用 (首次请求)...")
|
| 47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
# 初始化订阅管理器
|
| 49 |
sub_manager = SubscriptionManager(
|
| 50 |
sub_url=SUB_URL,
|
| 51 |
+
config_path=os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "config.yaml")
|
| 52 |
)
|
| 53 |
|
| 54 |
# 加载订阅并转换为Clash配置
|
|
|
|
| 64 |
|
| 65 |
# 初始化Clash管理器
|
| 66 |
clash_manager = ClashManager(
|
| 67 |
+
config_path=os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "config.yaml"),
|
| 68 |
clash_path=os.path.join(os.path.dirname(os.path.dirname(__file__)), "clash_core", "clash.meta-linux-amd64"),
|
| 69 |
api_port=CLASH_API_PORT,
|
| 70 |
proxy_port=CLASH_PROXY_PORT
|
|
|
|
| 452 |
</html>
|
| 453 |
"""
|
| 454 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 455 |
if __name__ == "__main__":
|
| 456 |
# 如果直接运行此文件,将初始化应用并启动Flask服务器
|
| 457 |
initialize_once()
|
entrypoint.sh
CHANGED
|
@@ -53,24 +53,10 @@ if [ -f ".env" ]; then
|
|
| 53 |
export $(grep -v '^#' .env | xargs -d '\n')
|
| 54 |
fi
|
| 55 |
|
| 56 |
-
#
|
| 57 |
-
if [ "$
|
| 58 |
-
echo "${
|
| 59 |
-
|
| 60 |
-
if [ -f "/app/data/config.yaml" ]; then
|
| 61 |
-
echo "${GREEN}Local config.yaml found${NC}"
|
| 62 |
-
else
|
| 63 |
-
echo "${RED}Error: Local config.yaml not found in /app/data/!${NC}"
|
| 64 |
-
echo "${YELLOW}Please mount your config.yaml to /app/data/config.yaml${NC}"
|
| 65 |
-
exit 1
|
| 66 |
-
fi
|
| 67 |
-
else
|
| 68 |
-
# 检查必要的环境变量
|
| 69 |
-
if [ -z "$SUB_URL" ]; then
|
| 70 |
-
echo "${RED}Error: SUB_URL environment variable is not set!${NC}"
|
| 71 |
-
echo "${YELLOW}Either set SUB_URL or use USE_LOCAL_CONFIG=true${NC}"
|
| 72 |
-
exit 1
|
| 73 |
-
fi
|
| 74 |
fi
|
| 75 |
|
| 76 |
# 设置默认端口
|
|
@@ -88,11 +74,7 @@ echo "Environment:"
|
|
| 88 |
echo "FLASK_PORT: ${FLASK_PORT:-7860}"
|
| 89 |
echo "CLASH_PROXY_PORT: ${CLASH_PROXY_PORT:-7890}"
|
| 90 |
echo "CLASH_API_PORT: ${CLASH_API_PORT:-9090}"
|
| 91 |
-
|
| 92 |
-
echo "Using local config: YES"
|
| 93 |
-
else
|
| 94 |
-
echo "SUB_URL: [hidden]"
|
| 95 |
-
fi
|
| 96 |
echo "API_KEY: [hidden]"
|
| 97 |
|
| 98 |
# 检查必要的环境变量
|
|
|
|
| 53 |
export $(grep -v '^#' .env | xargs -d '\n')
|
| 54 |
fi
|
| 55 |
|
| 56 |
+
# 检查必要的环境变量
|
| 57 |
+
if [ -z "$SUB_URL" ]; then
|
| 58 |
+
echo "${RED}Error: SUB_URL environment variable is not set!${NC}"
|
| 59 |
+
exit 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
fi
|
| 61 |
|
| 62 |
# 设置默认端口
|
|
|
|
| 74 |
echo "FLASK_PORT: ${FLASK_PORT:-7860}"
|
| 75 |
echo "CLASH_PROXY_PORT: ${CLASH_PROXY_PORT:-7890}"
|
| 76 |
echo "CLASH_API_PORT: ${CLASH_API_PORT:-9090}"
|
| 77 |
+
echo "SUB_URL: [hidden]"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
echo "API_KEY: [hidden]"
|
| 79 |
|
| 80 |
# 检查必要的环境变量
|