From 7c4a244ce9469797577f55079ddf7ba049a14f3d Mon Sep 17 00:00:00 2001 From: WorkBuddy Date: Tue, 22 Sep 2026 14:14:53 +0800 Subject: [PATCH] =?UTF-8?q?fix(docker):=20=E9=A2=84=E5=88=9B=E5=BB=BA=20/a?= =?UTF-8?q?pp/logs=20=E5=B9=B6=E8=B5=8B=E5=B1=9E=E4=B8=BB,=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=8D=B7=E6=8C=82=E8=BD=BD=E7=82=B9=20root=20?= =?UTF-8?q?=E6=9D=83=E9=99=90=E6=8B=92=E7=BB=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 生产实测: applogs 命名卷挂到 /app/logs 时挂载点由 Docker 以 root:root 创建,而非 root 进程(profeto)写入 app.log 时 PermissionError(Errno 13), best-effort 降级生效但文件日志实际未启用。 - Dockerfile: 镜像内预创建 /app/logs 并 chown(chown -R 已有,覆盖新目录); 命名卷为空且首次挂载时 Docker 会复制镜像目录属主,重建镜像即可修复 - log_buffer: PermissionError 单独捕获,warning 给出可操作的排查方向 (镜像预建目录/chown/重建空卷),其余异常仍保持原通用降级 --- Dockerfile | 9 ++++++++- src/core/log_buffer.py | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f592023..bcba46a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,14 @@ RUN pip install --no-cache-dir -r requirements.txt COPY src ./src RUN pip install --no-cache-dir . -# 将工作目录所有权移交给非 root 用户 +# 日志目录预创建: compose 运行时把 applogs 命名卷挂到 /app/logs, +# 卷挂载点默认由 Docker 以 root:root 创建 —— 镜像内不预建的话, +# 非 root 进程写日志会 PermissionError(Errno 13)。 +# 命名卷为空且首次挂载时,Docker 会复制镜像内该目录的内容与属主, +# 因此在这里 mkdir + chown 即可让卷目录归 profeto 所有。 +RUN mkdir -p /app/logs + +# 将工作目录所有权移交给非 root 用户(含上面的日志目录) RUN chown -R profeto:profeto /app EXPOSE 8000 diff --git a/src/core/log_buffer.py b/src/core/log_buffer.py index 3dfb4e7..b3deda9 100644 --- a/src/core/log_buffer.py +++ b/src/core/log_buffer.py @@ -112,6 +112,15 @@ def setup_logging(level: str = "INFO", log_file: str = "") -> None: file_handler.addFilter(_SQLNoiseFilter()) root.addHandler(file_handler) logging.getLogger(__name__).info("文件日志已启用: %s", log_file) + except PermissionError: + # 容器场景最常见:挂载卷目录属主是 root,进程是非 root 用户。 + # 修复方向:镜像内预创建目录并 chown(Dockerfile),或重建空卷。 + logging.getLogger(__name__).warning( + "启用文件日志失败(%s):无写权限。容器部署请确认镜像已预创建该目录" + "并 chown 给运行用户(compose 卷挂载点默认 root 属主);" + "宿主机直跑请检查目录权限。本次仅保留 stdout/内存日志。", + log_file, + ) except Exception: logging.getLogger(__name__).warning( "启用文件日志失败(%s),仅保留 stdout/内存日志", log_file, exc_info=True,