如何使用非root用户权限构建Docker镜像以设置带有pipenv的Python应用程序?

19

我使用Tornado服务器创建了Python Web应用程序,现在正在进行Docker化。我正在尝试构建用于持续集成和持续交付的Docker镜像。我已经能够使用root用户创建Docker镜像。现在我想使用非root用户构建Docker镜像,并使用pipenv设置应用程序。

Dockerfile

FROM python:3.6

RUN apt-get update -y

ENV USER dockeruser
ENV HOME /home/$USER

RUN useradd -m $USER && echo $USER:$USER | chpasswd && adduser $USER sudo
RUN chown $USER:$USER $HOME

USER $USER

RUN mkdir -p $HOME/myapp
COPY . $HOME/myapp
WORKDIR $HOME/myapp

RUN echo $(whoami)
RUN pip3 install pipenv --user
RUN echo $(which python)
RUN echo $(which pipenv)
RUN pipenv install --system --deploy --ignore-pipfile

EXPOSE 8002

# Run server.py when container launches
CMD gunicorn -k tornado server:app -b 0.0.0.0:8002 -w 4 -p server.pid

在构建镜像时出现了pipenv未找到的问题。

docker build -f Dockerfile -t myapp .
Sending build context to Docker daemon   51.2kB
Step 1/17 : FROM python:3.6
 ---> 1ec4d11819ad
Step 2/17 : RUN apt-get update -y
 ---> Using cache
 ---> 010d1ef4aee8
Step 3/17 : ENV USER dockeruser
 ---> Using cache
 ---> 9b9825691f31
Step 4/17 : ENV HOME /home/$USER
 ---> Using cache
 ---> 4002da8d84bf
Step 5/17 : RUN useradd -m $USER && echo $USER:$USER | chpasswd && adduser $USER sudo
 ---> Using cache
 ---> e6105957751e
Step 6/17 : RUN chown $USER:$USER $HOME
 ---> Using cache
 ---> e1b4d901ae9f
Step 7/17 : USER $USER
 ---> Using cache
 ---> e22af3515d86
Step 8/17 : RUN mkdir -p $HOME/myapp
 ---> Using cache
 ---> 6a7e99189ad8
Step 9/17 : COPY . $HOME/myapp
 ---> Using cache
 ---> f6e7ac570431
Step 10/17 : WORKDIR $HOME/myapp
 ---> Using cache
 ---> a0eaa4346a8c
Step 11/17 : RUN echo $(whoami)
 ---> Running in 60e249e38e94
dockeruser
Removing intermediate container 60e249e38e94
 ---> 015dfa644ff0
Step 12/17 : RUN pip3 install pipenv --user
 ---> Running in 5966183d82b0
Collecting pipenv
  Downloading https://files.pythonhosted.org/packages/13/b4/3ffa55f77161cff9a5220f162670f7c5eb00df52e00939e203f601b0f579/pipenv-2018.11.26-py3-none-any.whl (5.2MB)
Collecting virtualenv-clone>=0.2.5 (from pipenv)
  Downloading https://files.pythonhosted.org/packages/16/9d/6419a4f0fe4350db7fdc01e9d22e949779b6f2d2650e4884aa8aededc5ae/virtualenv_clone-0.4.0-py2.py3-none-any.whl
Collecting virtualenv (from pipenv)
  Downloading https://files.pythonhosted.org/packages/7c/17/9b7b6cddfd255388b58c61e25b091047f6814183e1d63741c8df8dcd65a2/virtualenv-16.1.0-py2.py3-none-any.whl (1.9MB)
Collecting certifi (from pipenv)
  Downloading https://files.pythonhosted.org/packages/9f/e0/accfc1b56b57e9750eba272e24c4dddeac86852c2bebd1236674d7887e8a/certifi-2018.11.29-py2.py3-none-any.whl (154kB)
Requirement already satisfied: pip>=9.0.1 in /usr/local/lib/python3.6/site-packages (from pipenv) (18.1)
Requirement already satisfied: setuptools>=36.2.1 in /usr/local/lib/python3.6/site-packages (from pipenv) (40.6.2)
Installing collected packages: virtualenv-clone, virtualenv, certifi, pipenv
  The script virtualenv-clone is installed in '/home/dockeruser/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  The script virtualenv is installed in '/home/dockeruser/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
  The scripts pipenv and pipenv-resolver are installed in '/home/dockeruser/.local/bin' which is not on PATH.
  Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
Successfully installed certifi-2018.11.29 pipenv-2018.11.26 virtualenv-16.1.0 virtualenv-clone-0.4.0
Removing intermediate container 5966183d82b0
 ---> 22aee2cc9a96
Step 13/17 : RUN echo $(which python)
 ---> Running in 140c3fa728f6
/usr/local/bin/python
Removing intermediate container 140c3fa728f6
 ---> 86816d83b846
Step 14/17 : RUN echo $(which pipenv)
 ---> Running in ac211799f058

Removing intermediate container ac211799f058
 ---> cf1b7ea148bb
Step 15/17 : RUN pipenv install --system --deploy --ignore-pipfile
 ---> Running in 47f0837ce1d7
/bin/sh: 1: pipenv: not found
The command '/bin/sh -c pipenv install --system --deploy --ignore-pipfile' returned a non-zero code: 127
4个回答

12

在Docker镜像中“全局”安装软件(通常只做一件事情)并承诺一些实现细节,比如容器内用户名和路径是没有问题的。完全可以作为root用户安装软件,并切换到非root用户来运行该镜像。

我可能会像这样编写Dockerfile:

FROM python:3.6

# Globally install pipenv
RUN pip3 install pipenv

# Set up the app directory (Docker will create it for us)
WORKDIR /myapp
COPY . ./
RUN pipenv install --system --deploy --ignore-pipfile

# Establish the runtime user (with no password and no sudo)
RUN useradd -m myapp
USER myapp

# Normal image metadata
EXPOSE 8002
CMD gunicorn -k tornado server:app -b 0.0.0.0:8002 -w 4 -p server.pid

David Maze 对其进行了微小的更改,以便在创建用户和权限以工作目录。 - prasannaboga
1
这些东西故意不在这里:您的运行时用户不应具有写入权限以更改您的服务代码,并且在隔离环境中运行“apt-get update”没有任何有用的作用。 - David Maze

6

您需要将pipenv添加到PATH变量中。

RUN echo $(whoami)
RUN pip3 install pipenv --user
ENV PATH $PATH:$HOME/.local/bin

应该是这样的。


它也适用于裸的“pip” +1。 - Denis Trofimov

2

您的安装日志已经给出了答案:

脚本 virtualenv-clone 已经安装在 '/home/dockeruser/.local/bin',但该目录不在 PATH 路径中。

这告诉您将无法通过简短的名称访问已安装的软件包。您可以使用完整路径名来调用它,例如 /home/dockeruser/.local/bin/... 或将此目录添加到 PATH 中。


0

当发出pip install --user指令时,软件包会落在用户主目录的子文件夹以及它们的脚本中。

在您的Docker镜像中,该子文件夹未列在PATH环境变量中,因此无法直接从shell调用脚本。但是,这些软件包很可能可以无问题地导入,因此您可以将pipenv作为Python模块而不是“脚本”运行。

USER $USER
RUN pip install --user pipenv
RUN python -m pipenv install --deploy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接