文件
workbuddy-portal/Dockerfile
T
wangchuanli 1bf961f6b3 feat(权限): 收敛普通账号写权限至本人凭证
将调度时刻、采集参数等实例级配置收归管理员,普通账号仅可维护本人 Cookie 与 User-Agent。
新增 config.writable_by 作为唯一写权限入口,set_setting 强制全局键落到 user_id=0,
消除「管理员改了只有自己生效」的静默缺陷。新增 tools/check_docs.py 文档自检,
smoke 断言扩至 215 项、check_live 扩至 122 项并支持普通账号越权验收,
忽略 backups/、data/*.bak* 与 legacy-v1/,版本升至 v1.3.0。
2026-09-18 08:46:00 +08:00

74 行
2.5 KiB
Docker

# syntax=docker/dockerfile:1
# =============================================================================
# workbuddy-portal —— 多阶段构建
# 构建层:只做「装依赖」,与源码解耦(改业务代码不会触发重装依赖)
# 运行层:slim 基础镜像 + 独立 venv + 非 root 用户
# =============================================================================
# ---------- Stage 1: 依赖 ----------
FROM python:3.13-slim AS builder
ENV PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1
# 单独建 venv:运行时整目录拷过去,镜像里不留 pip 缓存与编译工具
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
WORKDIR /build
COPY requirements.txt ./
RUN pip install --upgrade pip \
&& pip install -r requirements.txt
# ---------- Stage 2: 运行 ----------
FROM python:3.13-slim AS runtime
LABEL org.opencontainers.image.title="WorkBuddy Portal" \
org.opencontainers.image.description="WorkBuddy 积分用量采集 / 存储 / 呈现一体化门户" \
org.opencontainers.image.version="1.3.0" \
org.opencontainers.image.source="https://git.iwali.top/wangchuanli/workbuddy-portal"
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONIOENCODING=utf-8 \
TZ=Asia/Shanghai \
PATH="/opt/venv/bin:$PATH" \
WB_DATA_DIR=/app/data \
WB_LOG_DIR=/app/logs \
WB_HOST=0.0.0.0 \
WB_PORT=8848
# tzdata:日志与「每日 09:00 / 17:00」的调度槽位都依赖本地时区
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends tzdata ca-certificates; \
rm -rf /var/lib/apt/lists/*; \
ln -snf "/usr/share/zoneinfo/${TZ}" /etc/localtime; \
echo "${TZ}" > /etc/timezone; \
groupadd --gid 1000 app; \
useradd --uid 1000 --gid app --create-home --shell /usr/sbin/nologin app
COPY --from=builder /opt/venv /opt/venv
WORKDIR /app
# --chown 让非 root 用户能读写挂载卷之外的文件;.dockerignore 已挡掉数据与日志
COPY --chown=app:app . .
RUN set -eux; \
chmod +x /app/docker/entrypoint.sh /app/docker/healthcheck.py; \
mkdir -p /app/data /app/logs; \
chown -R app:app /app/data /app/logs; \
python -c "import workbuddy_portal, flask, waitress; print('deps ok', flask.__version__)"
USER app
EXPOSE 8848
VOLUME ["/app/data", "/app/logs"]
HEALTHCHECK --interval=30s --timeout=6s --start-period=20s --retries=3 \
CMD ["python", "/app/docker/healthcheck.py"]
ENTRYPOINT ["/app/docker/entrypoint.sh"]
CMD ["serve"]