在 Dockerfile 中设置非 root 用户并安装 pip 包

bga*_*ial 8 python docker

我有这个多阶段构建:

\n
FROM mcr.microsoft.com/azure-functions/python:3.0-python3.8 as intermediate\n\nRUN apt-get update && \\\n    apt-get install -y apt-utils && apt-get install -y git && \\\n    wget https://packages.microsoft.com/config/ubuntu/20.10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && \\\n    dpkg -i packages-microsoft-prod.deb && \\\n    apt-get update; \\\n    apt-get install -y apt-transport-https && \\\n    apt-get update && \\\n    apt-get install -y dotnet-sdk-5.0\n\nARG SPECKLE_ENFORCE_SSL\nENV SPECKLE_ENFORCE_SSL=false\nARG ARTIFACTS_KEYRING_NONINTERACTIVE_MODE\nENV ARTIFACTS_KEYRING_NONINTERACTIVE_MODE=true\n\nARG AZ_DEVOPS_TOKEN\nENV AZ_DEVOPS_TOKEN=$AZ_DEVOPS_TOKEN\nENV PYTHONUNBUFFERED 1\n\n\nRUN pip install --upgrade pip --no-cache-dir && \\\n    pip install pyyaml numpy lxml artifacts-keyring pytest --no-cache-dir && \\\n    pip install -i https://$AZ_DEVOPS_TOKEN@pkgs.dev.azure.com/<org>/<project>/_packaging/<feed>/pypi/simple/ --no-cache-dir <package-name>\n\n# Ditch the intermediate layer\n# IN THIS FINAL STAGE I WANT TO ADD AN USER AND USE IT\n\nFROM mcr.microsoft.com/azure-functions/python:3.0-python3.8\n\nENV AzureWebJobsScriptRoot=/home/site/wwwroot \\\n  AzureFunctionsJobHost__Logging__Console__IsEnabled=true\n\nCOPY --from=intermediate /usr/local/lib/python3.8/site-packages/ /usr/local/lib/python3.8/site-packages/\nADD requirements.txt /\n\n# SO I DID THE FOLLOWING: \nRUN addgroup --system --gid 1250 appgroup \\\n&& adduser --system -uid 1250 --ingroup appgroup --shell /bin/sh appuser && \\\necho \'%sudo ALL=(ALL) NOPASSWD:ALL\' >> /etc/sudoers\nRUN chown -R 1250:1250 /home/ && chmod -R 0700 /home/\nUSER appuser\n\nRUN pip install -r /requirements.txt\n\nADD . /home/appuser/wwwroot\nWORKDIR /home/appuser/wwwroot/HttpUploadTrigger/\n#RUN export PATH=/home/.local/bin:$PATH\n\n# I  CANNOT INSTALL pytest package \nRUN pip install pytest && pytest --verbose\n
Run Code Online (Sandbox Code Playgroud)\n

在第二阶段,我添加了appgroup组和appuser属于该addgroup组的用户

\n

当我删除RUN pip install pytest && pytest --verbose上面的行时,我正在使用 appuser 来运行容器,然后我得到了这个:

\n
> docker exec -ti af-fem-uploader bash\nappuser@fdf737a9e6ae:~/appuser/wwwroot/HttpUploadTrigger$\n
Run Code Online (Sandbox Code Playgroud)\n

但是当我添加该RUN pip install pytest && pytest --verbose步骤时,我的构建输出是:

\n
> CACHED [stage-1 4/9] RUN addgroup --system --gid 1250 appgroup && adduser --system -uid 1250 --ingroup appgroup --shell /bin/sh appuser && echo \'%sudo ALL=  0.0s\n => CACHED [stage-1 5/9] RUN chown -R 1250:1250 /home/ && chmod -R 0700 /home/                                                                                   0.0s\n => CACHED [stage-1 6/9] RUN pip install -r /requirements.txt                                                                                                    0.0s\n => [stage-1 7/9] ADD . /home/appuser/wwwroot                                                                                                                    0.1s\n => [stage-1 8/9] WORKDIR /home/appuser/wwwroot/HttpUploadTrigger/                                                                                               0.0s\n => ERROR [stage-1 9/9] RUN pip install pytest && pytest --verbose                                                                                               1.0s\n------\n > [stage-1 9/9] RUN pip install pytest && pytest --verbose:\n#15 0.785 Defaulting to user installation because normal site-packages is not writeable\n#15 0.815 Requirement already satisfied: pytest in /usr/local/lib/python3.8/site-packages (6.2.2)\n#15 0.825 Requirement already satisfied: pluggy<1.0.0a1,>=0.12 in /usr/local/lib/python3.8/site-packages (from pytest) (0.13.1)\n#15 0.827 Requirement already satisfied: packaging in /usr/local/lib/python3.8/site-packages (from pytest) (20.9)\n#15 0.828 Requirement already satisfied: attrs>=19.2.0 in /usr/local/lib/python3.8/site-packages (from pytest) (20.3.0)\n#15 0.829 Requirement already satisfied: py>=1.8.2 in /usr/local/lib/python3.8/site-packages (from pytest) (1.10.0)\n#15 0.830 Requirement already satisfied: toml in /usr/local/lib/python3.8/site-packages (from pytest) (0.10.2)\n#15 0.830 Requirement already satisfied: iniconfig in /usr/local/lib/python3.8/site-packages (from pytest) (1.1.1)\n#15 0.852 Requirement already satisfied: pyparsing>=2.0.2 in /usr/local/lib/python3.8/site-packages (from packaging->pytest) (2.4.7)\n#15 1.007 /bin/sh: 1: pytest: not found\n------\nexecutor failed running [/bin/sh -c pip install pytest && pytest --verbose]: exit code: 127\n
Run Code Online (Sandbox Code Playgroud)\n

看起来该pytest包无法安装,因为某些权限被拒绝,也许是因为我正在使用运行容器appuser

\n

我对此不太确定

\n
\n

更新

\n

我通过在第一阶段创建虚拟环境并将其复制到最后阶段来重新定义 Dockerfile,例如@Itamar Turner-Trauring在下面的回答中指出了我。

\n

文档文件是:

\n
FROM mcr.microsoft.com/azure-functions/python:3.0-python3.8 as intermediate\n\nRUN apt-get update && \\\n    apt-get install -y apt-utils && apt-get install -y git && \\\n    apt-get install -y --no-install-recommends build-essential gcc && \\\n    wget https://packages.microsoft.com/config/ubuntu/20.10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb && \\\n    dpkg -i packages-microsoft-prod.deb && \\\n    apt-get update; \\\n    apt-get install -y apt-transport-https && \\\n    apt-get update && \\\n    apt-get install -y dotnet-sdk-5.0\n\nARG SPECKLE_ENFORCE_SSL\nENV SPECKLE_ENFORCE_SSL=false\nARG ARTIFACTS_KEYRING_NONINTERACTIVE_MODE\nENV ARTIFACTS_KEYRING_NONINTERACTIVE_MODE=true\n\n# AZ_DEVOPS_TOKEN is a PAT from Azure DevOps with Packaging and Build scope privileges\nARG AZ_DEVOPS_TOKEN\nENV AZ_DEVOPS_TOKEN=$AZ_DEVOPS_TOKEN\nENV PYTHONUNBUFFERED 1\n\nENV VIRTUAL_ENV=/opt/env\nRUN python -m venv $VIRTUAL_ENV\n# Make sure we use the virtualenv:\nENV PATH="$VIRTUAL_ENV/bin::/home/.local/bin:$PATH"\n\nRUN pip install --upgrade pip && \\\n    pip install pyyaml numpy lxml artifacts-keyring && \\\n    pip install -i https://$AZ_DEVOPS_TOKEN@pkgs.dev.azure.com/corporateroot/DataFusr%20FEM-client/_packaging/rhdhv_fem/pypi/simple/ --no-cache-dir rhdhv-fem\n\n# Ditch the intermediate layer\nFROM mcr.microsoft.com/azure-functions/python:3.0-python3.8\nRUN useradd --create-home appuser\nCOPY --from=intermediate /home/.local/ /home/.local/\nRUN chown -R appuser /home/.local/\nUSER appuser\n\nENV AzureWebJobsScriptRoot=/home/appuser/wwwroot \\\n  AzureFunctionsJobHost__Logging__Console__IsEnabled=true\n\n# COPY --from=intermediate /usr/local/lib/python3.8/site-packages/ /usr/local/lib/python3.8/site-packages/\nCOPY --from=intermediate --chown=appuser $VIRTUAL_ENV /opt/venv\nADD requirements.txt /\n# Make sure we use the virtualenv:\nENV PATH="/opt/venv/bin:/home/.local/bin:$PATH"\nRUN pip install -r /requirements.txt\n\nADD . /home/appuser/wwwroot\nWORKDIR /home/appuser/wwwroot/HttpUploadTrigger/\nRUN pip install pytest && pytest --verbose\n
Run Code Online (Sandbox Code Playgroud)\n

当我运行构建时,执行最后一行时得到以下输出RUN pip install pytest && pytest --verbose

\n
 [stage-1 10/10] RUN pip install pytest && pytest --verbose:\n#17 1.053 WARNING: The directory \'/home/.cache/pip\' or its parent directory is not owned or is not writable by the current user. The cache has been disabled. Check the permissions and owner of that directory. If executing pip with sudo, you may want sudo\'s -H flag.\n#17 1.055 Defaulting to user installation because normal site-packages is not writeable\n#17 1.394 Collecting pytest\n#17 1.589   Downloading pytest-6.2.2-py3-none-any.whl (280 kB)\n#17 2.024 Collecting attrs>=19.2.0\n#17 2.050   Downloading attrs-20.3.0-py2.py3-none-any.whl (49 kB)\n
Run Code Online (Sandbox Code Playgroud)\n

尽管工作流程继续进行,但最终我得到了这个错误

\n
17 2.811 Successfully installed attrs-20.3.0 iniconfig-1.1.1 packaging-20.9 pluggy-0.13.1 py-1.10.0 pyparsing-2.4.7 pytest-6.2.2 toml-0.10.2\n#17 3.037 WARNING: You are using pip version 20.3.3; however, version 21.0.1 is available.\n#17 3.037 You should consider upgrading via the \'/usr/local/bin/python -m pip install --upgrade pip\' command.\n#17 3.434 ============================= test session starts ==============================\n#17 3.434 platform linux -- Python 3.8.7, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 -- /usr/local/bin/python\n#17 3.434 cachedir: .pytest_cache\n#17 3.434 rootdir: /home/appuser/wwwroot/HttpUploadTrigger\n#17 3.434 collecting ... collected 0 items / 1 error\n#17 3.778\n#17 3.778 ==================================== ERRORS ====================================\n#17 3.778 _____________________ ERROR collecting test_httptrigger.py _____________________\n#17 3.778 ImportError while importing test module \'/home/appuser/wwwroot/HttpUploadTrigger/test_httptrigger.py\'.\n#17 3.778 Hint: make sure your test modules/packages have valid Python names.\n#17 3.778 Traceback:\n#17 3.778 /usr/local/lib/python3.8/importlib/__init__.py:127: in import_module\n#17 3.778     return _bootstrap._gcd_import(name[level:], package, level)\n#17 3.778 __init__.py:16: in <module>\n#17 3.778     from rhdhv_fem.fem_SCIAutils import _fem_scia_to_fem\n#17 3.778 E   ModuleNotFoundError: No module named \'rhdhv_fem\'\n
Run Code Online (Sandbox Code Playgroud)\n

这表明尽管安装了我的私有包(我安装的包https://$AZ_DEVOPS_TOKEN@pkgs.dev.azure.com/corporateroot/DataFusr%20FEM-client/_packaging/rhdhv_fem/pypi/simple/ --no-cache-dir rhdhv-fem),但无法从执行中读取它pytest

\n

请注意,我还需要在最后阶段开始时从第一个中间阶段复制“/home/.local/”目录,并授予我的应用程序用户权限,例如:

\n
# Ditch the intermediate layer\nFROM mcr.microsoft.com/azure-functions/python:3.0-python3.8\nRUN useradd --create-home appuser\nCOPY --from=intermediate /home/.local/ /home/.local/\nRUN chown -R appuser /home/.local/\nUSER appuser\n
Run Code Online (Sandbox Code Playgroud)\n

我不确定,因为我正在复制虚拟环境并且没有使用 pip\xe2\x80\x99s--user选项,为什么这些文件被安装在 .local 目录中,例如此处突出显示的...

\n

Ita*_*ing 5

如果您想在一个映像中安装并在另一个映像中运行,通常更容易安装到 virtualenv 并复制 virtualenv,因为这样您就可以获得所有文件,例如数据文件和可执行文件等。复制站点包并不能解决这个问题。

然后,您可以在复制时将 virtualenv chown 给新用户。

就像是

FROM python:3.9-slim AS compile-image
RUN apt-get update
RUN apt-get install -y --no-install-recommends build-essential gcc

RUN python -m venv /opt/venv
# Make sure we use the virtualenv:
ENV PATH="/opt/venv/bin:$PATH"

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY setup.py .
COPY myapp/ .
RUN pip install .

FROM python:3.9-slim AS build-image
RUN useradd --create-home appuser
USER appuser
COPY --from=compile-image --chown=appuser /opt/venv /opt/venv

# Make sure we use the virtualenv:
ENV PATH="/opt/venv/bin:$PATH"
CMD ['myapp']
Run Code Online (Sandbox Code Playgroud)

--chown请注意in的使用,COPY以确保它在复制时更改所有权。(基于https://pythonspeed.com/articles/activate-virtualenv-dockerfile/https://pythonspeed.com/articles/multi-stage-docker-python/ https://pythonspeed.com/articles/root-能力-docker-安全/


Joa*_*ino -1

您可以将USER some_user 添加到您的 Dockerfile o使用特定用户运行

\n
cat Dockerfile\n...    \nUSER site\nRUN echo \'RUNNING as $USER\'\n
Run Code Online (Sandbox Code Playgroud)\n

我运行了图像

\n

或者在执行时

\n
docker run -it --user site image_name bash\n
Run Code Online (Sandbox Code Playgroud)\n

我不知道 USER 指令 s\xc3\xb3 是否有限制,您可以尝试添加RUN root到中间容器中,然后添加RUN site到最终容器中。

\n

我运行了提到的图像,其中没有用户站点,也许你想要的用户是www-data

\n