Docker容器中缺少Python包

6
我正在Docker容器中的tensorflow笔记本上工作。我通过pipenv在构建容器阶段安装其他依赖项。奇怪的是,一些明确安装的包,例如"certifi",似乎没有出现在python环境中。
我已经尝试使用RUN命令安装它,切换Pipfile的Python版本,并将几乎所有内容添加到PATH和PYTHONPATH环境变量中。奇怪的是,如果我登录到容器并手动执行安装,它就可以完美运行。
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-06bc95e4104d> in <module>
      6 # data wrangling
      7 import json
----> 8 import spacy
      9 from langdetect import detect
     10 import psycopg2

~usr/local/lib/python3.5/dist-packages/spacy/__init__.py in <module>
     10 from thinc.neural.util import prefer_gpu, require_gpu
     11 
---> 12 from .cli.info import info as cli_info
     13 from .glossary import explain
     14 from .about import __version__

~usr/local/lib/python3.5/dist-packages/spacy/cli/__init__.py in <module>
----> 1 from .download import download  # noqa: F401
      2 from .info import info  # noqa: F401
      3 from .link import link  # noqa: F401
      4 from .package import package  # noqa: F401
      5 from .profile import profile  # noqa: F401

~usr/local/lib/python3.5/dist-packages/spacy/cli/download.py in <module>
      3 
      4 import plac
----> 5 import requests
      6 import os
      7 import subprocess

~usr/local/lib/python3.5/dist-packages/requests/__init__.py in <module>
    110 from .__version__ import __copyright__, __cake__
    111 
--> 112 from . import utils
    113 from . import packages
    114 from .models import Request, Response, PreparedRequest

~usr/local/lib/python3.5/dist-packages/requests/utils.py in <module>
     22 
     23 from .__version__ import __version__
---> 24 from . import certs
     25 # to_native_string is unused here, but imported here for backwards compatibility
     26 from ._internal_utils import to_native_string

~usr/local/lib/python3.5/dist-packages/requests/certs.py in <module>
     13 packaged CA bundle.
     14 """
---> 15 from certifi import where
     16 
     17 if __name__ == '__main__':

ImportError: No module named 'certifi'


有人遇到过类似的问题吗?

最简单的复现设置如下:

docker-compose.yaml:

version: '3.1'
services:

  notebook:
    container_name: Notebook
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "5430:8888"
    user: ${CURRENT_UID}

Dockerfile:

FROM tensorflow/tensorflow:latest-py3-jupyter

RUN pip install --user pipenv
ENV PATH="/root/.local/bin:/.local/bin:${PATH}"
ENV PYTHONPATH="/usr/lib/python35.zip:/usr/lib/python3.5:/usr/lib/python3.5/plat-x86_64-linux-gnu:/usr/lib/python3.5/lib-dynload:/.local/lib/python3.5/site-packages:/usr/local/lib/python3.5/dist-packages:/usr/lib/python3/dist-packages:${PYTHONPATH}"

RUN apt-get update
RUN apt-get install -y libsm6 libxext6 libxrender-dev libglib2.0-0 postgresql libpq-dev

# We copy just the requirements.txt first to leverage Docker cache
COPY ./Pipfile ./Pipfile
COPY ./Pipfile.lock ./Pipfile.lock

RUN pipenv install --deploy --system --ignore-pipfile
RUN python -m spacy download xx

RUN pip install --user certifi

Pipfile:

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
numpy = "*"
scikit-learn = {extras = ["alldeps"]}
spacy = "*"
langdetect = "*"
ipykernel = "*"
bokeh = "*"
ipywidgets = "*"
plotly = "*"
lapjv = "*"
tensorflow = "*"
"psycopg2" = "*"
gensim = "*"
cmake = "*"
certifi = "*"

[dev-packages]

[requires]
python_version = "3.5"

使用 pipenv lock 锁定 Pipfile,使用 docker-compose up --build 构建并启动容器,登录容器后发现 certifi 包未安装。 非常感谢您的帮助!

1
如果您能创建一个最小化可重现示例,那么您更有可能得到答案。 - Mark A
好的,我添加了一个最小可重现示例。 - multiplex
如果在pipenv中设置了--ignore-pipfile,为什么还要担心Pipfile呢? - C.Nivs
因为我不想发布整个Pipfile.lock文件。它非常庞大,可能会因长度而被downvote。据我所知,pipenv lock命令应该生成相同的文件。但是说得好,我实际上可以从Dockerfile中删除COPY行。 - multiplex
显然,pipenv仍然希望使用Pipfile,无论标志如何。但这并不会改变很多事情。 - multiplex
2个回答

0
从你的dockerfile来看,似乎是在运行spacy之后安装certifi,而从堆栈跟踪可以看出spacy依赖于certifi。
RUN python -m spacy download xx

RUN pip install --user certifi

交换这些行的顺序以在依赖它的脚本运行之前安装它。

另外,请确保一切都配置为使用 python3,或显式使用 python3pip3


我尝试过了,但那似乎不是解决方案。实际上,我只添加了RUN pip ..命令,因为一开始它就无法工作。Pipfile中也将certifi作为显式依赖项。 - multiplex
也许spacy需要特定版本的certifi。如果certifi是spacy的依赖项,那么pip会在安装spacy时安装该版本,但当它开始安装certifi时,它会安装最新版本,因此与spacy不兼容。我对这些特定的软件包不熟悉,只是提供一个想法。 - ekmcd
我之所以添加了显式依赖项,是因为出现了问题 - 如果您想的话,这些都是我的调试过程中的产物 :) 我也考虑过这样的问题,但通常情况下pipenv应该会解决这种问题。 - multiplex

0

重启死亡问题:显然存在版本冲突,pip 无法解决。我转而使用Poetry作为模块管理解决方案,并以此规避了这个问题。


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