You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署FastAPI上传文件时出现Permission denied权限错误

Docker部署FastAPI上传文件权限拒绝问题解决

本地运行FastAPI文件上传接口时一切正常,但部署到Docker容器后出现权限错误,无法写入uploads目录。

报错信息

File "/app/main.py", line 26, in say_hello
    with open(file_path, "wb") as f:
         ^^^^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 13] Permission denied: 'uploads/h.png'

上传端点代码

@app.post("/letter")
async def say_hello(file: UploadFile = File(...)):
    
    file_path = f"uploads/{file.filename}"

    with open(file_path, "wb") as f:
        f.write(await file.read())
    return process_image(file_path)

Dockerfile内容

# syntax=docker/dockerfile:1

ARG PYTHON_VERSION=3.12.3
FROM python:${PYTHON_VERSION}-slim as base

ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

WORKDIR /app

ARG UID=10001
RUN adduser \
    --disabled-password \
    --gecos "" \
    --home "/nonexistent" \
    --shell "/sbin/nologin" \
    --no-create-home \
    --uid "${UID}" \
    appuser

# Set the permissions for all files
RUN chown -R appuser:appgroup /app

RUN --mount=type=cache,target=/root/.cache/pip \
    --mount=type=bind,source=requirements.txt,target=requirements.txt \
    python -m pip install -r requirements.txt

# Switch to the non-privileged user to run the application.
USER appuser

COPY . .

EXPOSE 8000

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

问题原因

  1. COPY指令权限问题:切换到appuser后执行COPY . .,复制的文件/目录默认所有者为root,导致appuser对uploads目录无写入权限。
  2. uploads目录未提前创建:若本地代码目录中不存在uploads文件夹,容器运行时代码尝试写入uploads/路径时,需要先创建目录,但appuser可能无权限在/app下创建新目录。
  3. 权限设置时机错误:RUN chown -R appuser:appgroup /app执行在COPY之前,后续复制的文件会新增root权限的内容,导致之前的权限设置失效。

解决方案

方案1:COPY时指定文件所有者

修改COPY指令,添加--chown参数确保复制的文件归appuser所有:

# 替换原COPY指令
COPY --chown=appuser:appuser . .

方案2:提前创建uploads目录并设置权限

在切换用户前创建uploads目录,赋予appuser权限:

# 在USER appuser之前添加
RUN mkdir -p /app/uploads && chown -R appuser:appuser /app/uploads

USER appuser
COPY . .

方案3:代码中自动创建uploads目录

在写入文件前检查并创建目录,避免因目录不存在导致的错误:

import os

@app.post("/letter")
async def say_hello(file: UploadFile = File(...)):
    upload_dir = "uploads"
    # 自动创建目录(已存在则跳过)
    os.makedirs(upload_dir, exist_ok=True)
    
    file_path = f"{upload_dir}/{file.filename}"
    with open(file_path, "wb") as f:
        f.write(await file.read())
    return process_image(file_path)

方案4:调整权限设置顺序

将chown命令移到COPY之后,确保所有文件都被赋予正确权限:

# 先复制文件,再设置权限
COPY . .
RUN chown -R appuser:appuser /app

# 再切换到非特权用户
USER appuser

内容的提问来源于stack exchange,提问作者dzmoxn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:05:37