diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..cf87a52 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,27 @@ +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +*.egg-info/ +.venv/ +venv/ + +# Git & CI +.git/ +.gitignore + +# Flask instance (SQLite + uploads) — 运行时生成,不进镜像 +instance/ +*.sqlite +*.sqlite3 +*.db + +# 交付物 & 生成测试脚本(非源码) +deliverables/ +*.sh +/tmp/ + +# 构建中间产物 +Dockerfile +.dockerignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4aded5f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,75 @@ +# ===================================================================== +# shell-gen - Linux 一键部署脚本生成器 (Flask Web 应用) +# +# 零 pip 依赖设计:除了 Flask,仅使用 Python 标准库。 +# 通过 PORT 环境变量控制监听端口(默认 5099)。 +# +# 构建: +# docker build -t shell-gen . +# +# 运行: +# docker run -d --name shell-gen -p 5099:5099 \ +# -e PORT=5099 \ +# -e SHELLGEN_SECRET='change-me' \ +# shell-gen +# +# 验证: +# curl http://localhost:5099/healthz +# # -> {"ok":true,"generators":50} +# ===================================================================== + +# ---------- 基础镜像 ---------- +# slim 版足够(项目只用 Flask + 标准库,无需编译工具) +FROM python:3.11-slim + +# ---------- 元信息 ---------- +LABEL org.opencontainers.image.title="shell-gen" \ + org.opencontainers.image.description="Linux 一键部署脚本生成器 (Flask)" \ + org.opencontainers.image.licenses="MIT" + +# 环境变量:缓冲输出便于 docker logs 实时查看 +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PORT=5099 \ + PIP_NO_CACHE_DIR=1 + +# ---------- 工作目录 ---------- +WORKDIR /app + +# ---------- 安装依赖 ---------- +# 唯一第三方依赖是 Flask;先复制 requirements 以利用层缓存 +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# ---------- 复制应用代码 ---------- +COPY app.py /app/app.py +COPY generators/ /app/generators/ +COPY templates/ /app/templates/ +COPY static/ /app/static/ +COPY README.md /app/README.md +COPY start.sh /app/start.sh + +# ---------- 非 root 运行 ---------- +# 创建专有运行用户,降低容器内权限风险 +RUN useradd --create-home --uid 10001 appuser \ + && mkdir -p /app/instance && chown -R appuser:appuser /app +USER appuser + +# ---------- 端口 & 健康检查 ---------- +EXPOSE 5099 +# 依赖 /healthz 路由做容器健康探针(无需额外工具) +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ + CMD python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:'+__import__('os').environ.get('PORT','5099')+'/healthz',timeout=3).status==200 else 1)" || exit 1 + +# ---------- 启动 ---------- +# 用 Flask 自带开发服务器(保持与项目 start.sh 一致的零依赖启动方式) +# 若要生产级并发,可改用 gunicorn:见下方注释 +CMD ["python", "app.py"] + +# ---------------- 生产并发方案(可选) ---------------- +# 如果希望多 worker 并发处理,取消下面注释并将上面的 CMD 替换: +# +# 1) 在 requirements.txt 增加一行:gunicorn +# 2) 将 CMD 改为: +# CMD ["gunicorn", "--bind", "0.0.0.0:5099", "--workers", "2", \ +# "--threads", "4", "--timeout", "60", "app:app"] diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..840d434 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +Flask>=3.0,<4.0