Docker运行触发PermissionError: '/nonexistent'权限拒绝问题求助
报错信息
Traceback (most recent call last): File "/usr/local/bin/pipenv", line 8, in <module> sys.exit(cli()) File "/usr/local/lib/python3.8/site-packages/pipenv/vendor/click/core.py", line 1130, in __call__ return self.main(*args, **kwargs) File "/usr/local/lib/python3.8/site-packages/pipenv/cli/options.py", line 58, in main return super().main(*args, **kwargs, windows_expand_args=False) File "/usr/local/lib/python3.8/site-packages/pipenv/vendor/click/core.py", line 1055, in main rv = self.invoke(ctx) File "/usr/local/lib/python3.8/site-packages/pipenv/vendor/click/core.py", line 1657, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) File "/usr/local/lib/python3.8/site-packages/pipenv/vendor/click/core.py", line 1404, in invoke return ctx.invoke(self.callback, **ctx.params) File "/usr/local/lib/python3.8/site-packages/pipenv/vendor/click/core.py", line 760, in invoke return __callback(*args, **kwargs) File "/usr/local/lib/python3.8/site-packages/pipenv/vendor/click/decorators.py", line 84, in new_func return ctx.invoke(f, obj, *args, **kwargs) File "/usr/local/lib/python3.8/site-packages/pipenv/vendor/click/core.py", line 760, in invoke return __callback(*args, **kwargs) File "/usr/local/lib/python3.8/site-packages/pipenv/cli/command.py", line 417, in run do_run( File "/usr/local/lib/python3.8/site-packages/pipenv/routines/shell.py", line 66, in do_run ensure_project( File "/usr/local/lib/python3.8/site-packages/pipenv/utils/project.py", line 30, in ensure_project if project.s.PIPENV_USE_SYSTEM or project.virtualenv_exists: File "/usr/local/lib/python3.8/site-packages/pipenv/project.py", line 411, in virtualenv_exists if os.path.exists(self.virtualenv_location): File "/usr/local/lib/python3.8/site-packages/pipenv/project.py", line 608, in virtualenv_location self._virtualenv_location = self.get_location_for_virtualenv() File "/usr/local/lib/python3.8/site-packages/pipenv/project.py", line 433, in get_location_for_virtualenv return str(get_workon_home().joinpath(self.virtualenv_name)) File "/usr/local/lib/python3.8/site-packages/pipenv/utils/shell.py", line 195, in get_workon_home os.makedirs(expanded_path, exist_ok=True) File "/usr/local/lib/python3.8/os.py", line 213, in makedirs makedirs(head, exist_ok=exist_ok) File "/usr/local/lib/python3.8/os.py", line 213, in makedirs makedirs(head, exist_ok=exist_ok) File "/usr/local/lib/python3.8/os.py", line 213, in makedirs makedirs(head, exist_ok=exist_ok) File "/usr/local/lib/python3.8/os.py", line 223, in makedirs mkdir(name, mode) PermissionError: [Errno 13] Permission denied: '/nonexistent'
对应的Dockerfile
ARG PYTHON_VERSION=3.8.2 FROM python:${PYTHON_VERSION}-slim as base ENV PYTHONDONTWRITEBYTECODE=1 WORKDIR /app ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ --home "/nonexistent" \ --shell "/sbin/nologin" \ --no-create-home \ --uid "${UID}" \ appuser COPY Pipfile Pipfile.lock ./ RUN pip install pipenv RUN pipenv install --deploy --ignore-pipfile USER appuser COPY . . EXPOSE 5000 CMD pipenv run python app.py
问题原因
Pipenv默认会读取当前用户的HOME目录来存储虚拟环境(路径通常为$HOME/.local/share/virtualenvs)。而Dockerfile中创建appuser时,指定了--home "/nonexistent"且加上--no-create-home参数,导致该目录不存在。切换到appuser执行pipenv run时,Pipenv尝试创建/nonexistent下的虚拟环境存储路径,但appuser没有权限在根目录创建/nonexistent目录,因此触发PermissionError。
解决方案
方案1:修改用户HOME目录为已存在的工作目录
将adduser中的--home参数改为容器内已存在的/app目录,并移除--no-create-home参数(或保留,因为WORKDIR已设置为/app,目录本身存在):
RUN adduser \ --disabled-password \ --gecos "" \ --home "/app" \ --shell "/sbin/nologin" \ --uid "${UID}" \ appuser
修改后,Pipenv会在/app/.local/share/virtualenvs下创建虚拟环境,appuser对/app目录拥有读写权限,可正常操作。
方案2:指定Pipenv在项目目录内创建虚拟环境
通过设置环境变量PIPENV_VENV_IN_PROJECT=1,让Pipenv将虚拟环境直接存放在项目目录下的.venv文件夹,无需依赖用户HOME目录。在Dockerfile中添加该环境变量:
ENV PIPENV_VENV_IN_PROJECT=1
建议放在RUN pip install pipenv之前,这样后续的pipenv install也会遵循这个配置,确保虚拟环境创建在项目目录内。
方案3:创建/nonexistent目录并授权
如果必须保留原用户配置,可手动创建/nonexistent目录并赋予appuser权限:
RUN adduser \ --disabled-password \ --gecos "" \ --home "/nonexistent" \ --shell "/sbin/nologin" \ --no-create-home \ --uid "${UID}" \ appuser && \ mkdir -p /nonexistent && \ chown appuser:appuser /nonexistent
这样Pipenv就能在该目录下创建所需的虚拟环境存储路径,不会触发权限错误。
内容的提问来源于stack exchange,提问作者Jianing JIA

